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,57 @@
1
+ module Trepan
2
+ class TraceCommand < OldCommand # :nodoc:
3
+ def regexp
4
+ /^\s* tr(?:ace)? (?: \s+ (\S+)) # on |off | var(iable)
5
+ (?: \s+ (\S+))? # (all | variable-name)?
6
+ (?: \s+ (\S+))? \s* # (stop | nostop)?
7
+ $/ix
8
+ end
9
+
10
+ def execute
11
+ if @match[1] =~ /on|off/
12
+ onoff = 'on' == @match[1]
13
+ if @match[2]
14
+ Debugger.current_context.tracing = onoff
15
+ print "Tracing %s all threads.\n" % (onoff ? 'on' : 'off')
16
+ else
17
+ Debugger.tracing = onoff
18
+ print "Tracing %s on current thread.\n" % (onoff ? 'on' : 'off')
19
+ end
20
+ elsif @match[1] =~ /var(?:iable)?/
21
+ varname=@match[2]
22
+ if debug_eval("defined?(#{varname})")
23
+ if @match[3] && @match[3] !~ /(:?no)?stop/
24
+ errmsg("expecting 'stop' or 'nostop'; got %s\n" % @match[3])
25
+ else
26
+ dbg_cmd = if @match[3] && (@match[3] !~ /nostop/)
27
+ 'debugger' else '' end
28
+ end
29
+ eval("
30
+ trace_var(:#{varname}) do |val|
31
+ print \"traced variable #{varname} has value \#{val}\n\"
32
+ #{dbg_cmd}
33
+ end")
34
+ else
35
+ errmsg "#{varname} is not a global variable.\n"
36
+ end
37
+ else
38
+ errmsg("expecting 'on', 'off', 'var' or 'variable'; got: %s\n" %
39
+ @match[1])
40
+ end
41
+ end
42
+
43
+ class << self
44
+ def help_command
45
+ 'trace'
46
+ end
47
+
48
+ def help(cmd)
49
+ %{
50
+ tr[ace] (on|off)\tset trace mode of current thread
51
+ tr[ace] (on|off) all\tset trace mode of all threads
52
+ tr[ace] var(iable) VARNAME [stop|nostop]\tset trace variable on VARNAME
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,199 @@
1
+ module Trepan
2
+ module VarFunctions # :nodoc:
3
+ def var_list(ary, b = get_binding)
4
+ ary.sort!
5
+ for v in ary
6
+ begin
7
+ s = debug_eval(v, b).inspect
8
+ rescue
9
+ begin
10
+ s = debug_eval(v, b).to_s
11
+ rescue
12
+ s = "*Error in evaluation*"
13
+ end
14
+ end
15
+ if s.size > self.class.settings[:width]
16
+ s[self.class.settings[:width]-3 .. -1] = "..."
17
+ end
18
+ print "%s = %s\n", v, s
19
+ end
20
+ end
21
+ def var_class_self
22
+ obj = debug_eval('self')
23
+ var_list(obj.class.class_variables, get_binding)
24
+ end
25
+ end
26
+
27
+ # Implements the debugger 'var class' command.
28
+ class VarClassVarCommand < OldCommand
29
+ def regexp
30
+ /^\s*v(?:ar)?\s+cl(?:ass)?/
31
+ end
32
+
33
+ def execute
34
+ unless @state.context
35
+ errmsg "can't get class variables here.\n"
36
+ return
37
+ end
38
+ var_class_self
39
+ end
40
+
41
+ class << self
42
+ def help_command
43
+ 'var'
44
+ end
45
+
46
+ def help(cmd)
47
+ %{
48
+ v[ar] cl[ass] \t\t\tshow class variables of self
49
+ }
50
+ end
51
+ end
52
+ end
53
+
54
+ class VarConstantCommand < OldCommand # :nodoc:
55
+ def regexp
56
+ /^\s*v(?:ar)?\s+co(?:nst(?:ant)?)?\s+/
57
+ end
58
+
59
+ def execute
60
+ obj = debug_eval(@match.post_match)
61
+ if obj.kind_of? Module
62
+ constants = debug_eval("#{@match.post_match}.constants")
63
+ constants.sort!
64
+ for c in constants
65
+ next if c =~ /SCRIPT/
66
+ value = obj.const_get(c) rescue "ERROR: #{$!}"
67
+ print " %s => %p\n", c, value
68
+ end
69
+ else
70
+ print "Should be Class/Module: %s\n", @match.post_match
71
+ end
72
+ end
73
+
74
+ class << self
75
+ def help_command
76
+ 'var'
77
+ end
78
+
79
+ def help(cmd)
80
+ %{
81
+ v[ar] c[onst] <object>\t\tshow constants of object
82
+ }
83
+ end
84
+ end
85
+ end
86
+
87
+ class VarGlobalCommand < OldCommand # :nodoc:
88
+ def regexp
89
+ /^\s*v(?:ar)?\s+g(?:lobal)?\s*$/
90
+ end
91
+
92
+ def execute
93
+ var_list(global_variables)
94
+ end
95
+
96
+ class << self
97
+ def help_command
98
+ 'var'
99
+ end
100
+
101
+ def help(cmd)
102
+ %{
103
+ v[ar] g[lobal]\t\t\tshow global variables
104
+ }
105
+ end
106
+ end
107
+ end
108
+
109
+ class VarInstanceCommand < OldCommand # :nodoc:
110
+ def regexp
111
+ /^\s*v(?:ar)?\s+ins(?:tance)?\s*/
112
+ end
113
+
114
+ def execute
115
+ obj = debug_eval(@match.post_match.empty? ? 'self' : @match.post_match)
116
+ var_list(obj.instance_variables, obj.instance_eval{binding()})
117
+ end
118
+
119
+ class << self
120
+ def help_command
121
+ 'var'
122
+ end
123
+
124
+ def help(cmd)
125
+ %{
126
+ v[ar] i[nstance] <object>\tshow instance variables of object
127
+ }
128
+ end
129
+ end
130
+ end
131
+
132
+ # Implements the debugger 'var local' command.
133
+ class VarLocalCommand < OldCommand
134
+ def regexp
135
+ /^\s*v(?:ar)?\s+l(?:ocal)?\s*$/
136
+ end
137
+
138
+ def execute
139
+ locals = @state.context.frame_locals(@state.frame_pos)
140
+ _self = @state.context.frame_self(@state.frame_pos)
141
+ locals.keys.sort.each do |name|
142
+ print " %s => %p\n", name, locals[name]
143
+ end
144
+ end
145
+
146
+ class << self
147
+ def help_command
148
+ 'var'
149
+ end
150
+
151
+ def help(cmd)
152
+ %{
153
+ v[ar] l[ocal]\t\t\tshow local variables
154
+ }
155
+ end
156
+ end
157
+ end
158
+
159
+ # Implements the debugger 'var inherit' command.
160
+ begin
161
+ require 'classtree'
162
+ have_classtree = true
163
+ rescue LoadError
164
+ have_classtree = false
165
+ end
166
+
167
+ class VarInheritCommand < OldCommand
168
+ def regexp
169
+ /^\s*v(?:ar)?\s+ct\s*/
170
+ end
171
+
172
+ def execute
173
+ unless @state.context
174
+ errmsg "can't get object inheritance.\n"
175
+ return
176
+ end
177
+ puts @match.post_match
178
+ obj = debug_eval("#{@match.post_match}.classtree")
179
+ if obj
180
+ print obj
181
+ else
182
+ errmsg "Trouble getting object #{@match.post_match}\n"
183
+ end
184
+ end
185
+
186
+ class << self
187
+ def help_command
188
+ 'var'
189
+ end
190
+
191
+ def help(cmd)
192
+ %{
193
+ v[ar] ct\t\t\tshow class heirarchy of object
194
+ }
195
+ end
196
+ end
197
+ end if have_classtree
198
+
199
+ end
@@ -0,0 +1,270 @@
1
+ require 'rubygems'
2
+ require 'columnize'
3
+ require 'require_relative'
4
+ require_relative './helper'
5
+
6
+ module Trepan
7
+ RUBY_DEBUG_DIR = File.expand_path(File.dirname(__FILE__)) unless
8
+ defined?(RUBY_DEBUG_DIR)
9
+
10
+ # A Trepan::Command object is is the base class for commands that
11
+ # implement a single debugger command. Individual debugger commands
12
+ # will be a subclass of this. The singleton class object is the
13
+ # command manager for all commands.
14
+ #
15
+ # Each debugger command is expected to implement the following methods:
16
+ # _regexp_:: A regular expression which input strings are matched
17
+ # against. If we have a match, run this command.
18
+ # It is the ruby-debug programmer's responsibility
19
+ # to make sure that these regular expressions match disjoint
20
+ # sets of strings. Otherwise one is arbitrarily used.
21
+ # _execute_:: Ruby code that implements the command.
22
+ # _help_:: Should return a String containing descriptive help for
23
+ # the commmand. Used by the 'help' command Trepan::HelpCommand
24
+ # _help_command_:: The name of the command listed via help.
25
+ #
26
+ # _help_ and _help_command_ methods are singleton methods, not
27
+ # instance methods like _regexp_ and _execute_.
28
+ class OldCommand
29
+ SubcmdStruct=Struct.new(:name, :min, :short_help, :long_help) unless
30
+ defined?(SubcmdStruct)
31
+
32
+ include Columnize
33
+
34
+ # Find _param_ in _subcmds_. The _param_ id downcased and can be
35
+ # abbreviated to the minimum length listed in the subcommands
36
+ def find(subcmds, param)
37
+ param.downcase!
38
+ for try_subcmd in subcmds do
39
+ if (param.size >= try_subcmd.min) and
40
+ (try_subcmd.name[0..param.size-1] == param)
41
+ return try_subcmd
42
+ end
43
+ end
44
+ return nil
45
+ end
46
+
47
+ class << self
48
+ # An Array containing Trepan::Command classes that implment each
49
+ # of the debugger commands.
50
+ def commands
51
+ @commands ||= []
52
+ end
53
+
54
+ DEF_OPTIONS = {
55
+ :allow_in_control => false,
56
+ :allow_in_post_mortem => true,
57
+ :event => true,
58
+ :always_run => 0,
59
+ :unknown => false,
60
+ :need_context => false,
61
+ } unless defined?(DEF_OPTIONS)
62
+
63
+ def inherited(klass)
64
+ DEF_OPTIONS.each do |o, v|
65
+ klass.options[o] = v if klass.options[o].nil?
66
+ end
67
+ commands << klass
68
+ end
69
+
70
+ # Read in and "include" all the subclasses of the
71
+ # Trepan::Command class. For example
72
+ # Trepan::QuitCommand is one of them. The list of Ruby
73
+ # files to read are all the files that end .rb in directory
74
+ # Trepan::RUBY_DEBUG_DIR
75
+ def load_commands
76
+ Dir[File.join(%W(#{Trepan.const_get(:RUBY_DEBUG_DIR)}
77
+ command-ruby-debug *))].each do
78
+ |file|
79
+ require file if file =~ /\.rb$/
80
+ end
81
+ Trepan.constants.grep(/Functions$/).map { |name| Trepan.const_get(name) }.each do |mod|
82
+ include mod
83
+ end
84
+ end
85
+
86
+ def method_missing(meth, *args, &block)
87
+ if meth.to_s =~ /^(.+?)=$/
88
+ @options[$1.intern] = args.first
89
+ else
90
+ if @options.has_key?(meth)
91
+ @options[meth]
92
+ else
93
+ super
94
+ end
95
+ end
96
+ end
97
+
98
+ def options
99
+ @options ||= {}
100
+ end
101
+
102
+ def settings_map
103
+ @@settings_map ||= {}
104
+ end
105
+ private :settings_map
106
+
107
+ # Returns a Hash of Debugger settings, @settings. If doesn't exist
108
+ # we create a @settings hash with [] setter and getter and return that.
109
+ def settings
110
+ unless true and defined? @settings and @settings
111
+ @settings = Object.new
112
+ map = settings_map
113
+ c = class << @settings; self end
114
+ if c.respond_to?(:funcall)
115
+ c.funcall(:define_method, :[]) do |name|
116
+ raise "No such setting #{name}" unless map.has_key?(name)
117
+ map[name][:getter].call
118
+ end
119
+ else
120
+ c.send(:define_method, :[]) do |name|
121
+ raise "No such setting #{name}" unless map.has_key?(name)
122
+ map[name][:getter].call
123
+ end
124
+ end
125
+ c = class << @settings; self end
126
+ if c.respond_to?(:funcall)
127
+ c.funcall(:define_method, :[]=) do |name, value|
128
+ raise "No such setting #{name}" unless map.has_key?(name)
129
+ map[name][:setter].call(value)
130
+ end
131
+ else
132
+ c.send(:define_method, :[]=) do |name, value|
133
+ raise "No such setting #{name}" unless map.has_key?(name)
134
+ map[name][:setter].call(value)
135
+ end
136
+ end
137
+ end
138
+ @settings
139
+ end
140
+
141
+ def register_setting_var(name, default)
142
+ var_name = "@@#{name}"
143
+ class_variable_set(var_name, default)
144
+ register_setting_get(name) { class_variable_get(var_name) }
145
+ register_setting_set(name) { |value| class_variable_set(var_name, value) }
146
+ end
147
+
148
+ def register_setting_get(name, &block)
149
+ settings_map[name] ||= {}
150
+ settings_map[name][:getter] = block
151
+ end
152
+
153
+ def register_setting_set(name, &block)
154
+ settings_map[name] ||= {}
155
+ settings_map[name][:setter] = block
156
+ end
157
+ end
158
+
159
+ register_setting_var(:basename, false) # use basename in showing files?
160
+ register_setting_var(:callstyle, :last)
161
+ register_setting_var(:debuggertesting, false)
162
+ register_setting_var(:force_stepping, false)
163
+ register_setting_var(:full_path, true)
164
+ register_setting_var(:listsize, 10) # number of lines in list command
165
+ register_setting_var(:stack_trace_on_error, false)
166
+ register_setting_var(:tracing_plus, false) # different linetrace lines?
167
+
168
+ # width of line output. Use COLUMNS value if it exists and is
169
+ # not too rediculously large.
170
+ width = ENV['COLUMNS'].to_i
171
+ width = 80 unless width > 10
172
+ register_setting_var(:width, width)
173
+
174
+ if not defined? Trepan::ARGV
175
+ Trepan::ARGV = ARGV.clone
176
+ end
177
+ register_setting_var(:argv, Trepan::ARGV)
178
+
179
+ def initialize(state)
180
+ @state = state
181
+ end
182
+
183
+ def match(input)
184
+ @match = regexp.match(input)
185
+ end
186
+
187
+ protected
188
+
189
+ # FIXME: use delegate?
190
+ def errmsg(*args)
191
+ @state.errmsg(*args)
192
+ end
193
+
194
+ def print(*args)
195
+ @state.print(*args)
196
+ end
197
+
198
+ # Called when we are about to do a dangerous operation. _msg_
199
+ # contains a prompt message. Return _true_ if confirmed or _false_
200
+ # if not confirmed.
201
+ def confirm(msg)
202
+ @state.confirm(msg) == 'y'
203
+ end
204
+
205
+ # debug_eval like Kernel.eval or Object.instance_eval but using
206
+ # the bindings for the debugged program. If there is a
207
+ # syntax-error like exception in running eval, print an
208
+ # appropriate message and throw :debug_error
209
+ def debug_eval(str, b = get_binding)
210
+ begin
211
+ val = eval(str, b)
212
+ rescue StandardError, ScriptError => e
213
+ if OldCommand.settings[:stack_trace_on_error]
214
+ at = eval("caller(1)", b)
215
+ print "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
216
+ for i in at
217
+ print "\tfrom %s\n", i
218
+ end
219
+ else
220
+ print "#{e.class} Exception: #{e.message}\n"
221
+ end
222
+ throw :debug_error
223
+ end
224
+ end
225
+
226
+ # debug_eval like Kernel.eval or Object.instance_eval but using
227
+ # the bindings for the debugged program. If there is a syntax
228
+ # error kind of exception in running eval, no warning is given and
229
+ # nil is returned.
230
+ def debug_silent_eval(str)
231
+ begin
232
+ eval(str, get_binding)
233
+ rescue StandardError, ScriptError
234
+ nil
235
+ end
236
+ end
237
+
238
+ # Return a binding object for the debugged program.
239
+ def get_binding
240
+ @state.context.frame_binding(@state.frame_pos)
241
+ end
242
+
243
+ def line_at(file, line)
244
+ Debugger.line_at(file, line)
245
+ end
246
+
247
+ def get_context(thnum)
248
+ Debugger.contexts.find{|c| c.thnum == thnum}
249
+ end
250
+ end
251
+
252
+ OldCommand.load_commands
253
+
254
+ # Returns setting object.
255
+ # Use Debugger.settings[] and Debugger.settings[]= methods to query and set
256
+ # debugger settings. These settings are available:
257
+ #
258
+ # - :autolist - automatically calls 'list' command on breakpoint
259
+ # - :autoeval - evaluates input in the current binding if it's not recognized as a debugger command
260
+ # - :autoirb - automatically calls 'irb' command on breakpoint
261
+ # - :stack_trace_on_error - shows full stack trace if eval command results with an exception
262
+ # - :frame_full_path - displays full paths when showing frame stack
263
+ # - :frame_class_names - displays method's class name when showing frame stack
264
+ # - :reload_source_on_change - makes 'list' command to always display up-to-date source code
265
+ # - :force_stepping - stepping command asways move to the new line
266
+ #
267
+ def self.settings
268
+ OldCommand.settings
269
+ end
270
+ end