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,199 @@
1
+ module Trepan
2
+ # Mix-in module to assist in command parsing.
3
+ module FrameFunctions # :nodoc:
4
+ def adjust_frame(frame_pos, absolute, context=@state.context)
5
+ @state.frame_pos = 0 if context != @state.context
6
+ if absolute
7
+ if frame_pos < 0
8
+ abs_frame_pos = context.stack_size + frame_pos
9
+ else
10
+ abs_frame_pos = frame_pos
11
+ end
12
+ else
13
+ abs_frame_pos = @state.frame_pos + frame_pos
14
+ end
15
+
16
+ if abs_frame_pos >= context.stack_size then
17
+ errmsg "Adjusting would put us beyond the oldest (initial) frame.\n"
18
+ return
19
+ elsif abs_frame_pos < 0 then
20
+ errmsg "Adjusting would put us beyond the newest (innermost) frame.\n"
21
+ return
22
+ end
23
+ if @state.frame_pos != abs_frame_pos then
24
+ @state.previous_line = nil
25
+ @state.frame_pos = abs_frame_pos
26
+ end
27
+
28
+ @state.file = context.frame_file(@state.frame_pos)
29
+ @state.line = context.frame_line(@state.frame_pos)
30
+
31
+ print_frame(@state.frame_pos, true)
32
+ end
33
+
34
+ def get_frame_call(prefix, pos, context)
35
+ id = context.frame_method(pos)
36
+ klass = context.frame_class(pos)
37
+ call_str = ""
38
+ if id
39
+ args = context.frame_args(pos)
40
+ locals = context.frame_locals(pos)
41
+ if OldCommand.settings[:callstyle] != :short && klass
42
+ if OldCommand.settings[:callstyle] == :tracked
43
+ arg_info = context.frame_args_info(pos)
44
+ end
45
+ call_str << "#{klass}."
46
+ end
47
+ call_str << id.id2name
48
+ if args.any?
49
+ call_str << "("
50
+ args.each_with_index do |name, i|
51
+ case OldCommand.settings[:callstyle]
52
+ when :short
53
+ call_str += "%s, " % [name]
54
+ when :last
55
+ klass = locals[name].class
56
+ if klass.inspect.size > 20+3
57
+ klass = klass.inspect[0..20]+"..."
58
+ end
59
+ call_str += "%s#%s, " % [name, klass]
60
+ when :tracked
61
+ if arg_info && arg_info.size > i
62
+ call_str += "#{name}: #{arg_info[i].inspect}, "
63
+ else
64
+ call_str += "%s, " % name
65
+ end
66
+ end
67
+ if call_str.size > self.class.settings[:width] - prefix.size
68
+ # Strip off trailing ', ' if any but add stuff for later trunc
69
+ call_str[-2..-1] = ",...XX"
70
+ break
71
+ end
72
+ end
73
+ call_str[-2..-1] = ")" # Strip off trailing ', ' if any
74
+ end
75
+ end
76
+ return call_str
77
+ end
78
+
79
+ def print_frame(pos, adjust = false, context=@state.context)
80
+ file = context.frame_file(pos)
81
+ line = context.frame_line(pos)
82
+ klass = context.frame_class(pos)
83
+
84
+ unless OldCommand.settings[:full_path]
85
+ path_components = file.split(/[\\\/]/)
86
+ if path_components.size > 3
87
+ path_components[0...-3] = '...'
88
+ file = path_components.join(File::ALT_SEPARATOR || File::SEPARATOR)
89
+ end
90
+ end
91
+
92
+ frame_num = "#%d " % pos
93
+ call_str = get_frame_call(frame_num, pos, context)
94
+ file_line = "at line %s:%d\n" % [CommandProcessor.canonic_file(file), line]
95
+ print frame_num
96
+ unless call_str.empty?
97
+ print call_str
98
+ print ' '
99
+ if call_str.size + frame_num.size + file_line.size > self.class.settings[:width]
100
+ print "\n "
101
+ end
102
+ end
103
+ print file_line
104
+ if Trepan.inside_emacs? && adjust
105
+ fmt = (Trepan.annotate.to_i > 1 ?
106
+ "\032\032source %s:%d\n" : "\032\032%s:%d\n")
107
+ print fmt % [CommandProcessor.canonic_file(file), line]
108
+ end
109
+ end
110
+
111
+ # Check if call stack is truncated. This can happen if
112
+ # Trepan.start is not called low enough in the call stack. An
113
+ # array of additional callstack lines from caller is returned if
114
+ # definitely truncated, false if not, and nil if we don't know.
115
+ #
116
+ # We determine truncation based on a passed in sentinal set via
117
+ # caller which can be nil.
118
+ #
119
+ # First we see if we can find our position in caller. If so, then
120
+ # we compare context position to that in caller using sentinal
121
+ # as a place to start ignoring additional caller entries. sentinal
122
+ # is set by rdebug, but if it's not set, i.e. nil then additional
123
+ # entries are presumably ones that we haven't recorded in context
124
+ def truncated_callstack?(context, sentinal=nil, cs=caller)
125
+ recorded_size = context.stack_size
126
+ to_find_fl = "#{context.frame_file(0)}:#{context.frame_line(0)}"
127
+ top_discard = false
128
+ cs.each_with_index do |fl, i|
129
+ fl.gsub!(/in `.*'$/, '')
130
+ fl.gsub!(/:$/, '')
131
+ if fl == to_find_fl
132
+ top_discard = i
133
+ break
134
+ end
135
+ end
136
+ if top_discard
137
+ cs = cs[top_discard..-1]
138
+ return false unless cs
139
+ return cs unless sentinal
140
+ if cs.size > recorded_size+2 && cs[recorded_size+2] != sentinal
141
+ # caller seems to truncate recursive calls and we don't.
142
+ # See if we can find sentinal in the first 0..recorded_size+1 entries
143
+ return false if cs[0..recorded_size+1].any?{ |f| f==sentinal }
144
+ return cs
145
+ end
146
+ return false
147
+ end
148
+ return nil
149
+ end
150
+
151
+
152
+ end
153
+
154
+ # Implements debugger "where" or "backtrace" command.
155
+ class OldWhereCommand < OldCommand
156
+ def regexp
157
+ /^\s*(?:old\-where)$/
158
+ end
159
+
160
+ def execute
161
+ (0...@state.context.stack_size).each do |idx|
162
+ if idx == @state.frame_pos
163
+ print "--> "
164
+ else
165
+ print " "
166
+ end
167
+ print_frame(idx)
168
+
169
+ end
170
+ if truncated_callstack?(@state.context, Trepan.start_sentinal)
171
+ print "Warning: saved frames may be incomplete;\n"
172
+ print "compare debugger backtrace (bt) with Ruby caller(0).\n"
173
+ end
174
+ end
175
+
176
+ class << self
177
+ def help_command
178
+ %w|oldwhere|
179
+ end
180
+
181
+ def help(cmd)
182
+ s = if cmd == 'oldwhere'
183
+ %{
184
+ w[here]\tdisplay stack frames
185
+ }
186
+ else
187
+ %{
188
+ bt|backtrace\t\talias for where - display stack frames
189
+ }
190
+ end
191
+ s += %{
192
+ Print the entire stack frame. Each frame is numbered, the most recent
193
+ frame is 0. frame number can be referred to in the "frame" command;
194
+ "up" and "down" add or subtract respectively to frame numbers shown.
195
+ The position of the current frame is marked with -->. }
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,63 @@
1
+ require 'rubygems'; require 'require_relative'
2
+ require_relative '../../app/options'
3
+ module Trepan
4
+
5
+ # Implements debugger "help" command.
6
+ class HelpCommand < OldCommand
7
+ self.allow_in_control = true
8
+
9
+ # An input line is matched against this regular expression. If we have
10
+ # a match, run this command.
11
+ def regexp
12
+ /^\s* h(?:elp)? (?:\s+(.+))? $/x
13
+ end
14
+
15
+ # The code that implements this command.
16
+ def execute
17
+ if @match[1]
18
+ args = @match[1].split
19
+ cmds = @state.commands.select do |cmd|
20
+ [cmd.help_command].flatten.include?(args[0])
21
+ end
22
+ else
23
+ args = @match[1]
24
+ cmds = []
25
+ end
26
+ unless cmds.empty?
27
+ help = cmds.map{ |cmd| cmd.help(args) }.join
28
+ help = help.split("\n").map{|l| l.gsub(/^ +/, '')}
29
+ help.shift if help.first && help.first.empty?
30
+ help.pop if help.last && help.last.empty?
31
+ print help.join("\n")
32
+ else
33
+ if args and args[0]
34
+ errmsg "Undefined command: \"#{args[0]}\". Try \"help\"."
35
+ else
36
+ print "#{Trepan::PROGRAM} help v#{Trepan::VERSION}\n" unless
37
+ self.class.settings[:debuggertesting]
38
+ print "Type 'help <command-name>' for help on a specific command\n\n"
39
+ print "Available commands:\n"
40
+ cmds = @state.commands.map{ |cmd| cmd.help_command }
41
+ cmds = cmds.flatten.uniq.sort
42
+ print columnize(cmds, self.class.settings[:width])
43
+ end
44
+ end
45
+ print "\n"
46
+ end
47
+
48
+ class << self
49
+ # The command name listed via 'help'
50
+ def help_command
51
+ 'help'
52
+ end
53
+
54
+ # Returns a String given the help description of this command
55
+ def help(cmd)
56
+ %{
57
+ h[elp]\t\tprint this help
58
+ h[elp] command\tprint help on command
59
+ }
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,359 @@
1
+ module Trepan
2
+ module InfoFunctions # :nodoc:
3
+ def info_catch(*args)
4
+ unless @state.context
5
+ print "No frame selected.\n"
6
+ return
7
+ end
8
+ if Debugger.catchpoints and not Debugger.catchpoints.empty?
9
+ # FIXME: show whether Exception is valid or not
10
+ # print "Exception: is_a?(Class)\n"
11
+ Debugger.catchpoints.each do |exception, hits|
12
+ # print "#{exception}: #{exception.is_a?(Class)}\n"
13
+ print "#{exception}\n"
14
+ end
15
+ else
16
+ print "No exceptions set to be caught.\n"
17
+ end
18
+ end
19
+ end
20
+
21
+ # Implements debugger "info" command.
22
+ class InfoCommand < OldCommand
23
+ self.allow_in_control = true
24
+ Subcommands =
25
+ [
26
+ ['display', 2, 'Expressions to display when program stops'],
27
+ ['file', 4, 'Info about a particular file read in',
28
+ '
29
+ After the file name is supplied, you can list file attributes that
30
+ you wish to see.
31
+
32
+ Attributes include: "all", "basic", "breakpoint", "lines", "mtime", "path"
33
+ and "sha1".'],
34
+ ['files', 5, 'File names and timestamps of files read in'],
35
+ ['global_variables', 2, 'Global variables'],
36
+ ['instance_variables', 2,
37
+ 'Instance variables of the current stack frame'],
38
+ ['locals', 2, 'Local variables of the current stack frame'],
39
+ ['stack', 2, 'Backtrace of the stack'],
40
+ ['thread', 6, 'List info about thread NUM', '
41
+ If no thread number is given, we list info for all threads. \'terse\' and \'verbose\'
42
+ options are possible. If terse, just give summary thread name information. See
43
+ "help info threads" for more detail about this summary information.
44
+
45
+ If \'verbose\' appended to the end of the command, then the entire
46
+ stack trace is given for each thread.'],
47
+ ['threads', 7, 'information of currently-known threads', '
48
+ This information includes whether the thread is current (+), if it is
49
+ suspended ($), or ignored (!). The thread number and the top stack
50
+ item. If \'verbose\' is given then the entire stack frame is shown.'],
51
+ ['variables', 1,
52
+ 'Local and instance variables of the current stack frame']
53
+ ].map do |name, min, short_help, long_help|
54
+ SubcmdStruct.new(name, min, short_help, long_help)
55
+ end unless defined?(Subcommands)
56
+
57
+ InfoFileSubcommands =
58
+ [
59
+ ['all', 1,
60
+ 'All file information available - breakpoints, lines, mtime, path, and sha1'],
61
+ ['basic', 2,
62
+ 'basic information - path, number of lines'],
63
+ ['breakpoints', 2, 'Show trace line numbers',
64
+ 'These are the line number where a breakpoint can be set.'],
65
+ ['lines', 1, 'Show number of lines in the file'],
66
+ ['mtime', 1, 'Show modification time of file'],
67
+ ['path', 4, 'Show full file path name for file'],
68
+ ['sha1', 1, 'Show SHA1 hash of contents of the file']
69
+ ].map do |name, min, short_help, long_help|
70
+ SubcmdStruct.new(name, min, short_help, long_help)
71
+ end unless defined?(InfoFileSubcommands)
72
+
73
+ InfoThreadSubcommands =
74
+ [
75
+ ['terse', 1, 'summary information'],
76
+ ['verbose', 1, 'summary information and stack frame info'],
77
+ ].map do |name, min, short_help, long_help|
78
+ SubcmdStruct.new(name, min, short_help, long_help)
79
+ end unless defined?(InfoThreadSubcommands)
80
+
81
+ def regexp
82
+ /^\s* i(?:nfo)? (?:\s+(.*))?$/ix
83
+ end
84
+
85
+ def execute
86
+ if !@match[1] || @match[1].empty?
87
+ errmsg "\"info\" must be followed by the name of an info command:\n"
88
+ print "List of info subcommands:\n\n"
89
+ for subcmd in Subcommands do
90
+ print "info #{subcmd.name} -- #{subcmd.short_help}\n"
91
+ end
92
+ else
93
+ args = @match[1].split(/[ \t]+/)
94
+ param = args.shift
95
+ subcmd = find(Subcommands, param)
96
+ if subcmd
97
+ send("info_#{subcmd.name}", *args)
98
+ else
99
+ errmsg "Unknown info command #{param}\n"
100
+ end
101
+ end
102
+ end
103
+
104
+ def info_display(*args)
105
+ unless @state.context
106
+ print "info display not available here.\n"
107
+ return
108
+ end
109
+ if @state.display.find{|d| d[0]}
110
+ print "Auto-display expressions now in effect:\n"
111
+ print "Num Enb Expression\n"
112
+ n = 1
113
+ for d in @state.display
114
+ print "%3d: %s %s\n", n, (d[0] ? 'y' : 'n'), d[1] if
115
+ d[0] != nil
116
+ n += 1
117
+ end
118
+ else
119
+ print "There are no auto-display expressions now.\n"
120
+ end
121
+ end
122
+
123
+ def info_file(*args)
124
+ unless args[0]
125
+ info_files
126
+ return
127
+ end
128
+ file = args[0]
129
+ param = args[1]
130
+
131
+ param = 'basic' unless param
132
+ subcmd = find(InfoFileSubcommands, param)
133
+ unless subcmd
134
+ errmsg "Invalid parameter #{param}\n"
135
+ return
136
+ end
137
+
138
+ unless LineCache::cached?(file)
139
+ unless LineCache::cached_script?(file)
140
+ print "File #{file} is not cached\n"
141
+ return
142
+ end
143
+ LineCache::cache(file, Command.settings[:reload_source_on_change])
144
+ end
145
+
146
+ print "File %s", file
147
+ path = LineCache.path(file)
148
+ if %w(all basic path).member?(subcmd.name) and path != file
149
+ print " - %s\n", path
150
+ else
151
+ print "\n"
152
+ end
153
+
154
+ if %w(all basic lines).member?(subcmd.name)
155
+ lines = LineCache.size(file)
156
+ print "\t %d lines\n", lines if lines
157
+ end
158
+
159
+ if %w(all breakpoints).member?(subcmd.name)
160
+ breakpoints = LineCache.trace_line_numbers(file)
161
+ if breakpoints
162
+ print "\tbreakpoint line numbers:\n"
163
+ print columnize(breakpoints.to_a.sort, self.class.settings[:width])
164
+ end
165
+ end
166
+
167
+ if %w(all mtime).member?(subcmd.name)
168
+ stat = LineCache.stat(file)
169
+ print "\t%s\n", stat.mtime if stat
170
+ end
171
+ if %w(all sha1).member?(subcmd.name)
172
+ print "\t%s\n", LineCache.sha1(file)
173
+ end
174
+ end
175
+
176
+ def info_instance_variables(*args)
177
+ unless @state.context
178
+ print "info instance_variables not available here.\n"
179
+ return
180
+ end
181
+ obj = debug_eval('self')
182
+ var_list(obj.instance_variables)
183
+ end
184
+
185
+ def info_locals(*args)
186
+ unless @state.context
187
+ errmsg "info line not available here.\n"
188
+ return
189
+ end
190
+ locals = @state.context.frame_locals(@state.frame_pos)
191
+ locals.keys.sort.each do |name|
192
+ ### FIXME: make a common routine
193
+ begin
194
+ s = "#{name} = #{locals[name].inspect}"
195
+ rescue
196
+ begin
197
+ s = "#{name} = #{locals[name].to_s}"
198
+ rescue
199
+ s = "*Error in evaluation*"
200
+ end
201
+ end
202
+ if s.size > self.class.settings[:width]
203
+ s[self.class.settings[:width]-3 .. -1] = "..."
204
+ end
205
+ print "#{s}\n"
206
+ end
207
+ end
208
+
209
+ def info_stack(*args)
210
+ if not @state.context
211
+ errmsg "info stack not available here.\n"
212
+ return
213
+ end
214
+ (0...@state.context.stack_size).each do |idx|
215
+ if idx == @state.frame_pos
216
+ print "--> "
217
+ else
218
+ print " "
219
+ end
220
+ print_frame(idx)
221
+ end
222
+ end
223
+
224
+ def info_thread_preamble(arg)
225
+ if not @state.context
226
+ errmsg "info threads not available here.\n"
227
+ return false, false
228
+ end
229
+ verbose = if arg
230
+ subcmd = find(InfoThreadSubcommands, arg)
231
+ unless subcmd
232
+ errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n"
233
+ return false, false
234
+ end
235
+ 'verbose' == subcmd.name
236
+ else
237
+ false
238
+ end
239
+ return true, verbose
240
+ end
241
+ private :info_thread_preamble
242
+
243
+ def info_threads(*args)
244
+ ok, verbose = info_thread_preamble(args[0])
245
+ return unless ok
246
+ threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c|
247
+ display_context(c, !verbose)
248
+ if verbose and not c.ignored?
249
+ (0...c.stack_size).each do |idx|
250
+ print "\t"
251
+ print_frame(idx, false, c)
252
+ end
253
+ end
254
+ end
255
+ end
256
+
257
+ def info_thread(*args)
258
+ unless args[0]
259
+ info_threads(args[0])
260
+ return
261
+ end
262
+ ok, verbose = info_thread_preamble(args[1])
263
+ return unless ok
264
+ c = parse_thread_num("info thread" , args[0])
265
+ return unless c
266
+ display_context(c, !verbose)
267
+ if verbose and not c.ignored?
268
+ (0...c.stack_size).each do |idx|
269
+ print "\t"
270
+ print_frame(idx, false, c)
271
+ end
272
+ end
273
+ end
274
+
275
+ def info_global_variables(*args)
276
+ unless @state.context
277
+ errmsg "info global_variables not available here.\n"
278
+ return
279
+ end
280
+ var_list(global_variables)
281
+ end
282
+
283
+ def info_variables(*args)
284
+ if not @state.context
285
+ errmsg "info variables not available here.\n"
286
+ return
287
+ end
288
+ obj = debug_eval('self')
289
+ locals = @state.context.frame_locals(@state.frame_pos)
290
+ locals['self'] = @state.context.frame_self(@state.frame_pos)
291
+ locals.keys.sort.each do |name|
292
+ next if name =~ /^__dbg_/ # skip debugger pollution
293
+ ### FIXME: make a common routine
294
+ begin
295
+ s = "#{name} = #{locals[name].inspect}"
296
+ rescue
297
+ begin
298
+ s = "#{name} = #{locals[name].to_s}"
299
+ rescue
300
+ s = "#{name} = *Error in evaluation*"
301
+ end
302
+ end
303
+ if s.size > self.class.settings[:width]
304
+ s[self.class.settings[:width]-3 .. -1] = "..."
305
+ end
306
+ s.gsub!('%', '%%') # protect against printf format strings
307
+ print "#{s}\n"
308
+ end
309
+ var_list(obj.instance_variables, obj.instance_eval{binding()})
310
+ var_class_self
311
+ end
312
+
313
+ class << self
314
+ def help_command
315
+ 'info'
316
+ end
317
+
318
+ def help(args)
319
+ if args[1]
320
+ s = args[1]
321
+ subcmd = Subcommands.find do |try_subcmd|
322
+ (s.size >= try_subcmd.min) and
323
+ (try_subcmd.name[0..s.size-1] == s)
324
+ end
325
+ if subcmd
326
+ str = subcmd.short_help + '.'
327
+ if 'file' == subcmd.name and args[2]
328
+ s = args[2]
329
+ subsubcmd = InfoFileSubcommands.find do |try_subcmd|
330
+ (s.size >= try_subcmd.min) and
331
+ (try_subcmd.name[0..s.size-1] == s)
332
+ end
333
+ if subsubcmd
334
+ str += "\n" + subsubcmd.short_help + '.'
335
+ else
336
+ str += "\nInvalid file attribute #{args[2]}."
337
+ end
338
+ else
339
+ str += "\n" + subcmd.long_help if subcmd.long_help
340
+ end
341
+ return str
342
+ else
343
+ return "Invalid 'info' subcommand '#{args[1]}'."
344
+ end
345
+ end
346
+ s = %{
347
+ Generic command for showing things about the program being debugged.
348
+ --
349
+ List of info subcommands:
350
+ --
351
+ }
352
+ for subcmd in Subcommands do
353
+ s += "info #{subcmd.name} -- #{subcmd.short_help}\n"
354
+ end
355
+ return s
356
+ end
357
+ end
358
+ end
359
+ end