rb8-trepanning 0.1.3

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 (274) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGES +34 -0
  3. data/ChangeLog +875 -0
  4. data/README.textile +59 -0
  5. data/Rakefile +215 -0
  6. data/app/.gitignore +1 -0
  7. data/app/cmd_parse.kpeg +241 -0
  8. data/app/cmd_parse.rb +212 -0
  9. data/app/cmd_parser.rb +1948 -0
  10. data/app/complete.rb +79 -0
  11. data/app/default.rb +90 -0
  12. data/app/display.rb +148 -0
  13. data/app/eventbuffer.rb +147 -0
  14. data/app/frame.rb +166 -0
  15. data/app/irb.rb +114 -0
  16. data/app/options.rb +200 -0
  17. data/app/run.rb +74 -0
  18. data/app/util.rb +65 -0
  19. data/bin/.gitignore +1 -0
  20. data/bin/trepan8 +115 -0
  21. data/data/.gitignore +1 -0
  22. data/data/irbrc +41 -0
  23. data/interface/.gitignore +1 -0
  24. data/interface/base_intf.rb +109 -0
  25. data/interface/client.rb +82 -0
  26. data/interface/comcodes.rb +20 -0
  27. data/interface/script.rb +110 -0
  28. data/interface/server.rb +147 -0
  29. data/interface/user.rb +165 -0
  30. data/io/base_io.rb +148 -0
  31. data/io/input.rb +158 -0
  32. data/io/null_output.rb +46 -0
  33. data/io/string_array.rb +156 -0
  34. data/io/tcpclient.rb +129 -0
  35. data/io/tcpfns.rb +33 -0
  36. data/io/tcpserver.rb +141 -0
  37. data/lib/debugger.rb +8 -0
  38. data/lib/trepanning.rb +283 -0
  39. data/processor/.gitignore +1 -0
  40. data/processor/command-ruby-debug/breakpoints.rb +155 -0
  41. data/processor/command-ruby-debug/catchpoint.rb +55 -0
  42. data/processor/command-ruby-debug/condition.rb +49 -0
  43. data/processor/command-ruby-debug/control.rb +31 -0
  44. data/processor/command-ruby-debug/display.rb +120 -0
  45. data/processor/command-ruby-debug/enable.rb +202 -0
  46. data/processor/command-ruby-debug/frame.rb +199 -0
  47. data/processor/command-ruby-debug/help.rb +63 -0
  48. data/processor/command-ruby-debug/info.rb +359 -0
  49. data/processor/command-ruby-debug/method.rb +84 -0
  50. data/processor/command-ruby-debug/reload.rb +40 -0
  51. data/processor/command-ruby-debug/save.rb +90 -0
  52. data/processor/command-ruby-debug/set.rb +237 -0
  53. data/processor/command-ruby-debug/show.rb +251 -0
  54. data/processor/command-ruby-debug/source.rb +36 -0
  55. data/processor/command-ruby-debug/threads.rb +189 -0
  56. data/processor/command-ruby-debug/trace.rb +57 -0
  57. data/processor/command-ruby-debug/variables.rb +199 -0
  58. data/processor/command.rb +270 -0
  59. data/processor/command/.gitignore +1 -0
  60. data/processor/command/alias.rb +54 -0
  61. data/processor/command/backtrace.rb +123 -0
  62. data/processor/command/base/cmd.rb +177 -0
  63. data/processor/command/base/subcmd.rb +230 -0
  64. data/processor/command/base/submgr.rb +188 -0
  65. data/processor/command/base/subsubcmd.rb +128 -0
  66. data/processor/command/base/subsubmgr.rb +199 -0
  67. data/processor/command/break.rb +114 -0
  68. data/processor/command/catch.rb +71 -0
  69. data/processor/command/complete.rb +39 -0
  70. data/processor/command/continue.rb +57 -0
  71. data/processor/command/directory.rb +50 -0
  72. data/processor/command/disable.rb +85 -0
  73. data/processor/command/display.rb +78 -0
  74. data/processor/command/down.rb +54 -0
  75. data/processor/command/edit.rb +79 -0
  76. data/processor/command/enable.rb +48 -0
  77. data/processor/command/eval.rb +90 -0
  78. data/processor/command/exit.rb +66 -0
  79. data/processor/command/finish.rb +59 -0
  80. data/processor/command/frame.rb +97 -0
  81. data/processor/command/help.rb +230 -0
  82. data/processor/command/help/.gitignore +1 -0
  83. data/processor/command/help/README +10 -0
  84. data/processor/command/help/command.txt +58 -0
  85. data/processor/command/help/examples.txt +16 -0
  86. data/processor/command/help/filename.txt +40 -0
  87. data/processor/command/help/location.txt +37 -0
  88. data/processor/command/help/suffixes.txt +17 -0
  89. data/processor/command/info.rb +28 -0
  90. data/processor/command/info_subcmd/.gitignore +1 -0
  91. data/processor/command/info_subcmd/args.rb +39 -0
  92. data/processor/command/info_subcmd/breakpoints.rb +80 -0
  93. data/processor/command/info_subcmd/catch.rb +36 -0
  94. data/processor/command/info_subcmd/files.rb +39 -0
  95. data/processor/command/info_subcmd/globals.rb +64 -0
  96. data/processor/command/info_subcmd/line.rb +30 -0
  97. data/processor/command/info_subcmd/locals.rb +69 -0
  98. data/processor/command/info_subcmd/macro.rb +62 -0
  99. data/processor/command/info_subcmd/program.rb +51 -0
  100. data/processor/command/info_subcmd/ruby.rb +57 -0
  101. data/processor/command/info_subcmd/source.rb +74 -0
  102. data/processor/command/info_subcmd/stack.rb +25 -0
  103. data/processor/command/info_subcmd/threads.rb +75 -0
  104. data/processor/command/kill.rb +78 -0
  105. data/processor/command/list.rb +117 -0
  106. data/processor/command/macro.rb +68 -0
  107. data/processor/command/next.rb +79 -0
  108. data/processor/command/parsetree.rb +56 -0
  109. data/processor/command/pp.rb +40 -0
  110. data/processor/command/pr.rb +37 -0
  111. data/processor/command/ps.rb +40 -0
  112. data/processor/command/restart.rb +86 -0
  113. data/processor/command/save.rb +58 -0
  114. data/processor/command/set.rb +47 -0
  115. data/processor/command/set_subcmd/.gitignore +1 -0
  116. data/processor/command/set_subcmd/abbrev.rb +25 -0
  117. data/processor/command/set_subcmd/auto.rb +27 -0
  118. data/processor/command/set_subcmd/auto_subcmd/.gitignore +1 -0
  119. data/processor/command/set_subcmd/auto_subcmd/eval.rb +53 -0
  120. data/processor/command/set_subcmd/auto_subcmd/irb.rb +33 -0
  121. data/processor/command/set_subcmd/auto_subcmd/list.rb +33 -0
  122. data/processor/command/set_subcmd/basename.rb +25 -0
  123. data/processor/command/set_subcmd/callstyle.rb +46 -0
  124. data/processor/command/set_subcmd/confirm.rb +24 -0
  125. data/processor/command/set_subcmd/debug.rb +47 -0
  126. data/processor/command/set_subcmd/different.rb +61 -0
  127. data/processor/command/set_subcmd/highlight.rb +43 -0
  128. data/processor/command/set_subcmd/max.rb +26 -0
  129. data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
  130. data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
  131. data/processor/command/set_subcmd/max_subcmd/string.rb +76 -0
  132. data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
  133. data/processor/command/set_subcmd/reload.rb +42 -0
  134. data/processor/command/set_subcmd/timer.rb +58 -0
  135. data/processor/command/set_subcmd/trace.rb +37 -0
  136. data/processor/command/set_subcmd/trace_subcmd/buffer.rb +42 -0
  137. data/processor/command/set_subcmd/trace_subcmd/print.rb +41 -0
  138. data/processor/command/shell.rb +139 -0
  139. data/processor/command/show.rb +39 -0
  140. data/processor/command/show_subcmd/.gitignore +1 -0
  141. data/processor/command/show_subcmd/abbrev.rb +20 -0
  142. data/processor/command/show_subcmd/alias.rb +46 -0
  143. data/processor/command/show_subcmd/args.rb +34 -0
  144. data/processor/command/show_subcmd/auto.rb +28 -0
  145. data/processor/command/show_subcmd/auto_subcmd/eval.rb +27 -0
  146. data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
  147. data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
  148. data/processor/command/show_subcmd/basename.rb +20 -0
  149. data/processor/command/show_subcmd/callstyle.rb +22 -0
  150. data/processor/command/show_subcmd/confirm.rb +18 -0
  151. data/processor/command/show_subcmd/debug.rb +26 -0
  152. data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
  153. data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
  154. data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
  155. data/processor/command/show_subcmd/different.rb +26 -0
  156. data/processor/command/show_subcmd/directories.rb +22 -0
  157. data/processor/command/show_subcmd/highlight.rb +24 -0
  158. data/processor/command/show_subcmd/max.rb +27 -0
  159. data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
  160. data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
  161. data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
  162. data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
  163. data/processor/command/show_subcmd/reload.rb +18 -0
  164. data/processor/command/show_subcmd/timer.rb +18 -0
  165. data/processor/command/show_subcmd/trace.rb +29 -0
  166. data/processor/command/show_subcmd/trace_subcmd/buffer.rb +65 -0
  167. data/processor/command/show_subcmd/trace_subcmd/print.rb +23 -0
  168. data/processor/command/show_subcmd/version.rb +23 -0
  169. data/processor/command/source.rb +134 -0
  170. data/processor/command/step.rb +81 -0
  171. data/processor/command/tbreak.rb +19 -0
  172. data/processor/command/unalias.rb +44 -0
  173. data/processor/command/undisplay.rb +59 -0
  174. data/processor/command/up.rb +72 -0
  175. data/processor/default.rb +56 -0
  176. data/processor/display.rb +17 -0
  177. data/processor/eval.rb +113 -0
  178. data/processor/eventbuf.rb +105 -0
  179. data/processor/frame.rb +172 -0
  180. data/processor/help.rb +92 -0
  181. data/processor/helper.rb +76 -0
  182. data/processor/hook.rb +134 -0
  183. data/processor/load_cmds.rb +258 -0
  184. data/processor/location.rb +174 -0
  185. data/processor/main.rb +455 -0
  186. data/processor/mock.rb +136 -0
  187. data/processor/msg.rb +61 -0
  188. data/processor/processor.rb +674 -0
  189. data/processor/running.rb +168 -0
  190. data/processor/stepping.rb +18 -0
  191. data/processor/subcmd.rb +161 -0
  192. data/processor/validate.rb +355 -0
  193. data/processor/virtual.rb +34 -0
  194. data/test/data/.gitignore +1 -0
  195. data/test/data/break_bad.cmd +19 -0
  196. data/test/data/break_bad.right +29 -0
  197. data/test/data/break_loop_bug.cmd +5 -0
  198. data/test/data/break_loop_bug.right +15 -0
  199. data/test/data/dollar-0.right +2 -0
  200. data/test/data/dollar-0a.right +2 -0
  201. data/test/data/dollar-0b.right +2 -0
  202. data/test/data/edit.cmd +14 -0
  203. data/test/data/edit.right +24 -0
  204. data/test/data/file-with-space.cmd +6 -0
  205. data/test/data/file-with-space.right +4 -0
  206. data/test/data/printvar.cmd +17 -0
  207. data/test/data/printvar.right +31 -0
  208. data/test/data/raise.cmd +11 -0
  209. data/test/data/raise.right +19 -0
  210. data/test/data/source.cmd +5 -0
  211. data/test/data/source.right +18 -0
  212. data/test/data/stepping-1.9.right +50 -0
  213. data/test/data/stepping.cmd +21 -0
  214. data/test/data/stepping.right +48 -0
  215. data/test/data/trepan8-save.1 +6 -0
  216. data/test/example/bp_loop_issue.rb +3 -0
  217. data/test/example/break-bug.rb +7 -0
  218. data/test/example/brkpt-class-bug.rb +8 -0
  219. data/test/example/classes.rb +11 -0
  220. data/test/example/dollar-0.rb +5 -0
  221. data/test/example/except-bug1.rb +4 -0
  222. data/test/example/except-bug2.rb +7 -0
  223. data/test/example/file with space.rb +1 -0
  224. data/test/example/gcd.rb +18 -0
  225. data/test/example/info-var-bug.rb +47 -0
  226. data/test/example/info-var-bug2.rb +2 -0
  227. data/test/example/null.rb +1 -0
  228. data/test/example/pm-bug.rb +3 -0
  229. data/test/example/pm.rb +11 -0
  230. data/test/example/raise.rb +3 -0
  231. data/test/integration/.gitignore +4 -0
  232. data/test/integration/config.yaml +8 -0
  233. data/test/integration/helper.rb +154 -0
  234. data/test/integration/test-break_bad.rb +26 -0
  235. data/test/integration/test-dollar-0.rb +31 -0
  236. data/test/integration/test-edit.rb +17 -0
  237. data/test/integration/test-file-with-space.rb +26 -0
  238. data/test/integration/test-printvar.rb +17 -0
  239. data/test/integration/test-raise.rb +21 -0
  240. data/test/integration/test-source.rb +16 -0
  241. data/test/integration/test-stepping.rb +24 -0
  242. data/test/unit/.gitignore +1 -0
  243. data/test/unit/cmd-helper.rb +52 -0
  244. data/test/unit/mock-helper.rb +12 -0
  245. data/test/unit/test-app-cmd_parse.rb +97 -0
  246. data/test/unit/test-app-cmd_parser.rb +23 -0
  247. data/test/unit/test-app-complete.rb +39 -0
  248. data/test/unit/test-app-frame.rb +32 -0
  249. data/test/unit/test-app-options.rb +92 -0
  250. data/test/unit/test-app-run.rb +14 -0
  251. data/test/unit/test-app-util.rb +44 -0
  252. data/test/unit/test-base-cmd.rb +45 -0
  253. data/test/unit/test-base-subcmd.rb +57 -0
  254. data/test/unit/test-base-submgr.rb +23 -0
  255. data/test/unit/test-base-subsubcmd.rb +17 -0
  256. data/test/unit/test-cmd-alias.rb +48 -0
  257. data/test/unit/test-cmd-exit.rb +27 -0
  258. data/test/unit/test-cmd-help.rb +104 -0
  259. data/test/unit/test-cmd-kill.rb +46 -0
  260. data/test/unit/test-cmd-source.rb +34 -0
  261. data/test/unit/test-completion.rb +42 -0
  262. data/test/unit/test-intf-user.rb +46 -0
  263. data/test/unit/test-io-input.rb +27 -0
  264. data/test/unit/test-io-tcp.rb +33 -0
  265. data/test/unit/test-io-tcpclient.rb +54 -0
  266. data/test/unit/test-io-tcpfns.rb +17 -0
  267. data/test/unit/test-io-tcpserver.rb +50 -0
  268. data/test/unit/test-proc-eval.rb +36 -0
  269. data/test/unit/test-proc-hook.rb +30 -0
  270. data/test/unit/test-proc-load_cmds.rb +50 -0
  271. data/test/unit/test-proc-location.rb +79 -0
  272. data/test/unit/test-subcmd-help.rb +44 -0
  273. data/trepan8.gemspec +52 -0
  274. metadata +391 -0
@@ -0,0 +1,174 @@
1
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require 'rubygems';
3
+ begin
4
+ require 'linecache'
5
+ rescue LoadError
6
+ require 'linecache19'
7
+ end
8
+ require 'require_relative'
9
+ # require_relative 'disassemble'
10
+ require_relative 'msg'
11
+ # require_relative 'frame'
12
+ # require_relative '../app/file'
13
+ require_relative 'virtual'
14
+ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
15
+
16
+ def canonic_file(filename, resolve=true)
17
+ # For now we want resolved filenames
18
+ if @settings[:basename]
19
+ return File.basename(filename)
20
+ end
21
+ if resolve
22
+ filename = LineCache::unmap_file(filename)
23
+ if !File.exist?(filename)
24
+ if (try_filename = resolve_file_with_dir(filename))
25
+ filename = try_filename if File.exist?(filename)
26
+ end
27
+ end
28
+ end
29
+ File.expand_path(filename)
30
+ end
31
+
32
+ # Return the text to the current source line.
33
+ def current_source_text
34
+ LineCache::getline(@frame.file, @frame.line).chomp
35
+ end
36
+
37
+ def resolve_file_with_dir(path_suffix)
38
+ settings[:directory].split(/:/).each do |dir|
39
+ dir =
40
+ if '$cwd' == dir
41
+ Dir.pwd
42
+ else
43
+ dir
44
+ end
45
+ next unless dir && File.directory?(dir)
46
+ try_file = File.join(dir, path_suffix)
47
+ return try_file if File.readable?(try_file)
48
+ end
49
+ nil
50
+ end
51
+
52
+ # Get line +line_number+ from file named +filename+. Return "\n"
53
+ # there was a problem. Leading blanks are stripped off.
54
+ def line_at(filename, line_number,
55
+ opts = {
56
+ :reload_on_change => @settings[:reload],
57
+ :output => @settings[:highlight]
58
+ })
59
+ # We use linecache first to give precidence to user-remapped
60
+ # file names
61
+ line = LineCache::getline(filename, line_number, opts)
62
+ unless line
63
+ # Try using search directories (set with command "directory")
64
+ if filename[0..0] != File::SEPARATOR
65
+ try_filename = resolve_file_with_dir(filename)
66
+ if try_filename &&
67
+ line = LineCache::getline(try_filename, line_number, opts)
68
+ LineCache::remap_file(filename, try_filename)
69
+ end
70
+ end
71
+ end
72
+ return nil unless line
73
+ return line.lstrip.chomp
74
+ end
75
+
76
+ def loc_and_text(opts=
77
+ {:reload_on_change => @settings[:reload],
78
+ :output => @settings[:highlight]
79
+ })
80
+
81
+ loc = source_location_info
82
+ line_no = @frame.line
83
+ filename = @frame.file
84
+
85
+ # if @frame.eval?
86
+ # file = LineCache::map_script(static.script)
87
+ # text = LineCache::getline(static.script, line_no, opts)
88
+ # loc += " remapped #{canonic_file(file)}:#{line_no}"
89
+ # else
90
+ text = line_at(filename, line_no, opts)
91
+ map_file, map_line = LineCache::unmap_file_line(filename, line_no)
92
+ if [filename, line_no] != [map_file, map_line]
93
+ loc += " remapped #{canonic_file(map_file)}:#{map_line}"
94
+ end
95
+ # end
96
+ [loc, line_no, text]
97
+ end
98
+
99
+ def format_location(event=@event, frame=@frame, frame_index=@frame.index)
100
+ text = nil
101
+ ev = if event.nil? || 0 != frame_index
102
+ ' '
103
+ else
104
+ (EVENT2ICON[event] || event)
105
+ end
106
+
107
+ @line_no = frame.line
108
+ loc, @line_no, text = loc_and_text
109
+
110
+ "#{ev} (#{loc}"
111
+ end
112
+
113
+ # FIXME: Use above format_location routine
114
+ def print_location
115
+ text = nil
116
+ ev = if @event.nil? || 0 != @frame.index
117
+ ' '
118
+ else
119
+ (EVENT2ICON[@event] || @event)
120
+ end
121
+
122
+ @line_no = @frame.line
123
+ loc, @line_no, text = loc_and_text
124
+
125
+ msg "#{ev} (#{loc})"
126
+
127
+ # if %w(return c-return).member?(@core.event)
128
+ # retval = Trepan::Frame.value_returned(@frame, @core.event)
129
+ # msg 'R=> %s' % retval.inspect
130
+ # end
131
+
132
+ if text && !text.strip.empty?
133
+ old_maxstring = @settings[:maxstring]
134
+ @settings[:maxstring] = -1
135
+ msg text
136
+ @settings[:maxstring] = old_maxstring
137
+ @line_no -= 1
138
+ end
139
+ end
140
+
141
+ def source_location_info
142
+ filename = @frame.file
143
+ canonic_filename =
144
+ ## if @frame.eval?
145
+ ## 'eval ' + safe_repr(@frame.eval_string.gsub("\n", ';').inspect, 20)
146
+ ## else
147
+ canonic_file(filename, false)
148
+ ## end
149
+ loc = "#{canonic_filename}:#{@frame.line}"
150
+ return loc
151
+ end
152
+ end
153
+
154
+ if __FILE__ == $0 && caller.size == 0
155
+ # Demo it.
156
+ require_relative './mock'
157
+ dbgr = MockDebugger::MockDebugger.new
158
+ proc = Trepan::CmdProcessor.new([Trepan::UserInterface.new(nil, nil,
159
+ :history_save=>false)])
160
+ proc.settings = {:directory => '$cdir:$cwd'}
161
+ proc.frame_initialize
162
+ require 'ruby-debug'; Debugger.start
163
+ proc.frame_setup(Debugger.current_context, nil)
164
+ puts proc.canonic_file(__FILE__)
165
+ proc.settings[:basename] = true
166
+ puts proc.canonic_file(__FILE__)
167
+ puts proc.current_source_text
168
+ xx = eval <<-END
169
+ proc.frame_initialize
170
+ proc.frame_setup(Debugger.current_context, nil)
171
+ puts proc.current_source_text
172
+ END
173
+ Debugger.stop
174
+ end
data/processor/main.rb ADDED
@@ -0,0 +1,455 @@
1
+ # Copyright (C) 2010, 2011 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
+
7
+ require 'rubygems'; require 'require_relative'
8
+ ## %w(default display eventbuf eval load_cmds location frame hook msg
9
+ ## validate).each do
10
+ # %w(default breakpoint disassemble display eval eventbuf load_cmds location
11
+ # frame hook msg running stepping validate).each do
12
+ %w(default display eval eventbuf frame hook load_cmds location msg running validate).each do
13
+ |mod_str|
14
+ require_relative mod_str
15
+ end
16
+ ## require_relative '../app/brkptmgr'
17
+
18
+ module Trepan
19
+ class CmdProcessor < VirtualCmdProcessor
20
+
21
+ # SEE ALSO attr's in require_relative's of loop above.
22
+
23
+ attr_reader :cmd_argstr # Current command args, a String.
24
+ # This is current_command with the command
25
+ # name removed from the beginning.
26
+ attr_reader :cmd_name # command name before alias or macro resolution
27
+ attr_reader :cmd_queue # queue of commands to run
28
+ ## attr_reader :core # Trepan core object
29
+ attr_reader :current_command # Current command getting run, a String.
30
+
31
+ attr_accessor :dbgr # Trepan instance (via
32
+ # Trepan::Core instance)
33
+ ## FIXME 1.9.2 has attr_reader !
34
+ attr_accessor :interfaces
35
+ attr_accessor :state
36
+
37
+ attr_accessor :debug_nest # Number of nested debugs. Used in showing
38
+ # prompt.
39
+ attr_accessor :different_pos # Same type as settings[:different]
40
+ # this is the temporary value for the
41
+ # next stop while settings is the default
42
+ # value to use.
43
+ attr_accessor :event # Stop event
44
+ attr_reader :intf # Current interface
45
+ # Trepan::Core instance)
46
+ attr_accessor :leave_cmd_loop # Commands set this to signal to leave
47
+ # the command loop (which often continues to
48
+ # run the debugged program).
49
+ attr_accessor :line_no # Last line shown in "list" command
50
+ attr_accessor :next_level # Fixnum. frame.stack_size has to
51
+ # be <= than this. If next'ing,
52
+ # this will be > 0.
53
+ attr_accessor :next_thread # Thread. If non-nil then in
54
+ # stepping the thread has to be
55
+ # this thread.
56
+ attr_accessor :pass_exception # Pass an exception back
57
+ attr_accessor :prompt # String print before requesting input
58
+ attr_reader :settings # Hash[:symbol] of command
59
+ # processor settings
60
+ attr_reader :step_bp
61
+
62
+ # The following are used in to force stopping at a different line
63
+ # number. FIXME: could generalize to a position object.
64
+ attr_accessor :last_pos # Last position. 6-Tuple: of
65
+ # [location, container, stack_size,
66
+ # current_thread, pc_offset]
67
+
68
+ unless defined?(EVENT2ICON)
69
+ # Event icons used in printing locations.
70
+ EVENT2ICON = {
71
+ 'brkpt' => 'xx',
72
+ 'tbrkpt' => 'x1',
73
+ 'c-call' => 'C>',
74
+ 'c-return' => '<C',
75
+ 'step-call' => '->',
76
+ 'call' => '->',
77
+ 'class' => '::',
78
+ 'coverage' => '[]',
79
+ 'debugger-call' => ':o',
80
+ 'end' => '-|',
81
+ 'line' => '--',
82
+ 'raise' => '!!',
83
+ 'return' => '<-',
84
+ 'start' => '>>',
85
+ 'switch' => 'sw',
86
+ 'trace-var' => '$V',
87
+ 'unknown' => '?!',
88
+ 'vm' => 'VM',
89
+ 'vm-insn' => '..',
90
+ }
91
+ # These events are important enough event that we always want to
92
+ # stop on them.
93
+ UNMASKABLE_EVENTS = Set.new(['end', 'raise', 'unknown'])
94
+ end
95
+
96
+ ## def initialize(dbgr, settings={})
97
+ def initialize(interfaces, settings={})
98
+ @cmd_queue = []
99
+ @event = nil
100
+ @interfaces = interfaces
101
+ @intf = interfaces[-1]
102
+ @debug_nest = 1
103
+ @hidelevels = {}
104
+ @last_command = nil
105
+ @last_pos = [nil, nil, nil, nil, nil, nil]
106
+ @next_level = 32000
107
+ @next_thread = nil
108
+ @user_variables = 0
109
+ @state = nil
110
+
111
+
112
+ start_cmds = settings.delete(:start_cmds)
113
+ start_file = settings.delete(:start_file)
114
+
115
+ @settings = DEFAULT_SETTINGS.merge(settings)
116
+ @different_pos = @settings[:different]
117
+
118
+ # FIXME: Rework using a general "set substitute file" command and
119
+ # a global default profile which gets read.
120
+ prelude_file = File.expand_path(File.join(File.dirname(__FILE__),
121
+ %w(.. data prelude.rb)))
122
+
123
+ # Start with empty thread and frame info.
124
+ frame_teardown
125
+
126
+ # Run initialization routines for each of the "submodule"s.
127
+ # load_cmds has to come first.
128
+ ## %w(load_cmds breakpoint display eventbuf frame running validate
129
+ ## ).each do |submod|
130
+ ## %w(load_cmds breakpoint display eventbuf frame running
131
+ ## stepping validate).each do
132
+ %w(load_cmds display eventbuf frame running validate).each do
133
+ |submod|
134
+ self.send("#{submod}_initialize")
135
+ end
136
+ hook_initialize(commands)
137
+ end
138
+
139
+ def compute_prompt
140
+ "(#{@settings[:prompt]}): "
141
+ end
142
+
143
+ def finalize
144
+ # breakpoint_finalize
145
+ # stepping_breakpoint_finalize
146
+ @intf.finalize
147
+ end
148
+
149
+ def canonic_container(container)
150
+ [container[0], canonic_file(container[1])]
151
+ end
152
+
153
+ def compute_prompt
154
+ "(#{@settings[:prompt]}): "
155
+ end
156
+
157
+ # Check that we meed the criteria that cmd specifies it needs
158
+ def ok_for_running(cmd, name, nargs)
159
+ # TODO check execution_set against execution status.
160
+ # Check we have frame is not null
161
+ min_args = cmd.class.const_get(:MIN_ARGS)
162
+ if nargs < min_args
163
+ errmsg(("Command '%s' needs at least %d argument(s); " +
164
+ "got %d.") % [name, min_args, nargs])
165
+ return false
166
+ end
167
+ max_args = cmd.class.const_get(:MAX_ARGS)
168
+ if max_args and nargs > max_args
169
+ errmsg(("Command '%s' needs at most %d argument(s); " +
170
+ "got %d.") % [name, max_args, nargs])
171
+ return false
172
+ end
173
+ # if cmd.class.const_get(:NEED_RUNNING) && !...
174
+ # errmsg "Command '%s' requires a running program." % name
175
+ # return false
176
+ # end
177
+
178
+ if cmd.class.const_get(:NEED_STACK) && !@context
179
+ errmsg "Command '%s' requires a running stack frame." % name
180
+ return false
181
+ end
182
+
183
+ return true
184
+ end
185
+
186
+ # Run one debugger command. True is returned if we want to quit.
187
+ def process_command_and_quit?()
188
+ intf_size = @interfaces.size
189
+ if @interfaces.empty?
190
+ puts "FOO"
191
+ exit
192
+ end
193
+ @intf = @interfaces[-1]
194
+ return true if @intf.input_eof? && intf_size == 1
195
+ while intf_size > 1 || !@intf.input_eof?
196
+ begin
197
+ @current_command =
198
+ if @cmd_queue.empty?
199
+ # Leave trailing blanks on for the "complete" command
200
+ read_command.chomp
201
+ else
202
+ @cmd_queue.shift
203
+ end
204
+ if @current_command.empty?
205
+ if @last_command && intf.interactive?
206
+ @current_command = @last_command
207
+ else
208
+ next
209
+ end
210
+ end
211
+ next if @current_command[0..0] == '#' # Skip comment lines
212
+ break
213
+ rescue IOError, Errno::EPIPE => e
214
+ if intf_size > 1
215
+ @interfaces.pop
216
+ intf_size = @interfaces.size
217
+ @intf = @interfaces.last
218
+ @last_command = nil
219
+ print_location
220
+ else
221
+ ## FIXME: think of something better.
222
+ quit('exit!')
223
+ return true
224
+ end
225
+ rescue Exception => exc
226
+ errmsg("Internal debugger error in read: #{exc.inspect}")
227
+ exception_dump(exc, @settings[:debugexcept], $!.backtrace)
228
+ end
229
+ end
230
+ run_command(@current_command)
231
+
232
+ # Save it to the history.
233
+ @intf.history_io.puts @last_command if @last_command && @intf.history_io
234
+ end
235
+
236
+ def after_cmdloop
237
+ @cmdloop_posthooks.run
238
+ end
239
+
240
+ def before_cmdloop
241
+
242
+ frame_setup(@context, @state)
243
+
244
+ @unconditional_prehooks.run
245
+ if breakpoint?
246
+ delete_breakpoint(@brkpt) if @brkpt.temp?
247
+ @last_pos = [@frame.vm_location, @stack_size, @current_thread, @event]
248
+ end
249
+
250
+ if stepping_skip? # || @stack_size <= @hide_level
251
+ if @next_thread
252
+ self.next(@step_count, :next_level => @next_level)
253
+ else
254
+ step(@return_to_program, @step_count, {}, @stop_condition)
255
+ end
256
+ return true
257
+ elsif @event == 'start'
258
+ step('step', 0)
259
+ return true
260
+ end
261
+
262
+ @prompt = compute_prompt
263
+
264
+ @leave_cmd_loop = false
265
+ print_location unless @settings[:traceprint]
266
+ # if 'trace-var' == @event
267
+ # msg "Note: we are stopped *after* the above location."
268
+ # end
269
+
270
+ @eventbuf.add_mark if @settings[:tracebuffer]
271
+
272
+ @return_to_program = false
273
+ @cmdloop_prehooks.run
274
+ return false
275
+ end
276
+
277
+ # This is the main entry point.
278
+ def process_commands(context, state)
279
+
280
+ @context = context
281
+ @state = state
282
+ frame_setup(@context, @state)
283
+ # @event = @core.event
284
+
285
+ @unconditional_prehooks.run
286
+ # if breakpoint?
287
+ # @last_pos = [@frame.source_container, frame_line,
288
+ # @stack_size, @current_thread, @event,
289
+ # @frame.pc_offset]
290
+ # else
291
+ # return if stepping_skip? || @stack_size <= @hide_level
292
+ # end
293
+
294
+ @prompt = compute_prompt
295
+
296
+ @leave_cmd_loop = false
297
+ print_location unless @settings[:traceprint]
298
+ # if 'trace-var' == @event
299
+ # msg "Note: we are stopped *after* the above location."
300
+ # end
301
+
302
+ @eventbuf.add_mark if @settings[:tracebuffer]
303
+
304
+ @cmdloop_prehooks.run
305
+ while not @leave_cmd_loop do
306
+ begin
307
+ break if process_command_and_quit?()
308
+ rescue SystemExit
309
+ @dbgr.stop
310
+ raise
311
+ rescue Exception => exc
312
+ # If we are inside the script interface errmsg may fail.
313
+ begin
314
+ errmsg("Internal debugger error in cmdloop: #{exc.inspect}")
315
+ rescue IOError
316
+ $stderr.puts "Internal debugger error: #{exc.inspect}"
317
+ end
318
+ exception_dump(exc, @settings[:debugexcept], $!.backtrace)
319
+ end
320
+ end
321
+ @cmdloop_posthooks.run
322
+ end
323
+
324
+ # Run current_command, a String. @last_command is set after the
325
+ # command is run if it is a command.
326
+ def run_command(current_command)
327
+ eval_command =
328
+ if current_command[0..0] == '!'
329
+ current_command[0] = ''
330
+ else
331
+ false
332
+ end
333
+
334
+ unless eval_command
335
+ commands = current_command.split(';;')
336
+ if commands.size > 1
337
+ current_command = commands.shift
338
+ @cmd_queue.unshift *commands
339
+ end
340
+ args = current_command.split
341
+ # Expand macros. FIXME: put in a procedure
342
+ while true do
343
+ macro_cmd_name = args[0]
344
+ return false if args.size == 0
345
+ break unless @macros.member?(macro_cmd_name)
346
+ current_command = @macros[macro_cmd_name][0].call(*args[1..-1])
347
+ msg current_command.inspect if settings[:debugmacro]
348
+ if current_command.is_a?(Array) &&
349
+ current_command.all? {|val| val.is_a?(String)}
350
+ args = (first=current_command.shift).split
351
+ @cmd_queue += current_command
352
+ current_command = first
353
+ elsif current_command.is_a?(String)
354
+ args = current_command.split
355
+ else
356
+ errmsg("macro #{macro_cmd_name} should return an Array " +
357
+ "of Strings or a String. Got #{current_command.inspect}")
358
+ return false
359
+ end
360
+ end
361
+
362
+ @cmd_name = args[0]
363
+ run_cmd_name =
364
+ if @aliases.member?(@cmd_name)
365
+ @aliases[@cmd_name]
366
+ else
367
+ @cmd_name
368
+ end
369
+
370
+ run_cmd_name = uniq_abbrev(@commands.keys, run_cmd_name) if
371
+ !@commands.member?(run_cmd_name) && @settings[:abbrev]
372
+
373
+ if @commands.member?(run_cmd_name)
374
+ cmd = @commands[run_cmd_name]
375
+ if ok_for_running(cmd, run_cmd_name, args.size-1)
376
+ @cmd_argstr = current_command[@cmd_name.size..-1].lstrip
377
+ cmd.run(args)
378
+ @last_command = current_command
379
+ end
380
+ return false
381
+ end
382
+ end
383
+
384
+ # Eval anything that's not a command or has been
385
+ # requested to be eval'd
386
+ if settings[:autoeval] || eval_command
387
+ begin
388
+ eval_code(current_command, @settings[:maxstring])
389
+ return false
390
+ rescue NameError
391
+ end
392
+ end
393
+ undefined_command(cmd_name)
394
+ end
395
+
396
+ # Error message when a command doesn't exist
397
+ def undefined_command(cmd_name)
398
+ begin
399
+ errmsg('Undefined command: "%s". Try "help".' % cmd_name)
400
+ rescue
401
+ $stderr.puts 'Undefined command: "%s". Try "help".' % cmd_name
402
+ end
403
+ end
404
+
405
+ # FIXME: Allow access to both Trepan::CmdProcessor and Trepan
406
+ # for index [] and []=.
407
+ # If there is a Trepan::CmdProcessor setting that would take precidence.
408
+ # def settings
409
+ # @settings.merge(@dbgr.settings) # wrong because this doesn't allow []=
410
+ # end
411
+ end
412
+ end
413
+
414
+ if __FILE__ == $0
415
+ $0 = 'foo' # So we don't get here again
416
+ require_relative '../lib/trepanning'
417
+ puts "To be continued...."
418
+ exit
419
+ dbg = Trepan.new(:nx => true)
420
+ cmdproc = dbg.instance_variable_get('@processor')
421
+ cmdproc.msg('I am main')
422
+ cmdproc.errmsg('Whoa!')
423
+ cmds = cmdproc.commands
424
+ p cmdproc.aliases
425
+ p cmdproc.commands.keys.sort
426
+ cmd_name, cmd_obj = cmds.first
427
+ puts cmd_obj.class.const_get(:HELP)
428
+ puts cmd_obj.class.const_get(:SHORT_HELP)
429
+
430
+ cmdproc.instance_variable_set('@current_thread', Thread.current)
431
+ puts cmdproc.compute_prompt
432
+ Thread.new{ puts cmdproc.compute_prompt }.join
433
+
434
+ x = Thread.new{ Thread.pass; x = 1 }
435
+ puts cmdproc.compute_prompt
436
+ x.join
437
+ cmdproc.debug_nest += 1
438
+ puts cmdproc.compute_prompt
439
+
440
+ # if ARGV.size > 0
441
+ # cmdproc.msg('Enter "q" to quit')
442
+ # cmdproc.process_commands
443
+ # else
444
+ # $input = []
445
+ # class << cmdproc
446
+ # def read_command
447
+ # $input.shift
448
+ # end
449
+ # end
450
+ # $input = ['1+2']
451
+ # cmdproc.process_command_and_quit?
452
+ # $input = ['!s = 5'] # ! means eval line
453
+ # cmdproc.process_command_and_quit?
454
+ # end
455
+ end