trepanning 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (219) hide show
  1. data/ChangeLog +4422 -0
  2. data/LICENSE +23 -0
  3. data/NEWS +12 -0
  4. data/README.textile +56 -0
  5. data/Rakefile +171 -0
  6. data/app/Makefile +7 -0
  7. data/app/breakpoint.rb +157 -0
  8. data/app/brkptmgr.rb +149 -0
  9. data/app/condition.rb +22 -0
  10. data/app/core.rb +203 -0
  11. data/app/default.rb +54 -0
  12. data/app/disassemble.rb +61 -0
  13. data/app/display.rb +148 -0
  14. data/app/file.rb +135 -0
  15. data/app/frame.rb +275 -0
  16. data/app/irb.rb +112 -0
  17. data/app/mock.rb +22 -0
  18. data/app/options.rb +122 -0
  19. data/app/run.rb +95 -0
  20. data/app/thread.rb +24 -0
  21. data/app/util.rb +32 -0
  22. data/bin/trepan +63 -0
  23. data/data/custom_require.rb +44 -0
  24. data/data/irbrc +55 -0
  25. data/data/prelude.rb +38 -0
  26. data/interface/base_intf.rb +95 -0
  27. data/interface/script.rb +103 -0
  28. data/interface/user.rb +90 -0
  29. data/io/base_io.rb +92 -0
  30. data/io/input.rb +111 -0
  31. data/io/string_array.rb +155 -0
  32. data/lib/Makefile +7 -0
  33. data/lib/trepanning.rb +277 -0
  34. data/processor/breakpoint.rb +108 -0
  35. data/processor/command/alias.rb +55 -0
  36. data/processor/command/backtrace.rb +95 -0
  37. data/processor/command/base/cmd.rb +97 -0
  38. data/processor/command/base/subcmd.rb +207 -0
  39. data/processor/command/base/submgr.rb +178 -0
  40. data/processor/command/base/subsubcmd.rb +102 -0
  41. data/processor/command/base/subsubmgr.rb +182 -0
  42. data/processor/command/break.rb +85 -0
  43. data/processor/command/condition.rb +64 -0
  44. data/processor/command/continue.rb +61 -0
  45. data/processor/command/debug.rb +85 -0
  46. data/processor/command/delete.rb +54 -0
  47. data/processor/command/directory.rb +43 -0
  48. data/processor/command/disable.rb +65 -0
  49. data/processor/command/disassemble.rb +103 -0
  50. data/processor/command/display.rb +81 -0
  51. data/processor/command/down.rb +56 -0
  52. data/processor/command/enable.rb +43 -0
  53. data/processor/command/exit.rb +54 -0
  54. data/processor/command/finish.rb +81 -0
  55. data/processor/command/frame.rb +117 -0
  56. data/processor/command/help.rb +146 -0
  57. data/processor/command/info.rb +28 -0
  58. data/processor/command/info_subcmd/args.rb +56 -0
  59. data/processor/command/info_subcmd/breakpoints.rb +162 -0
  60. data/processor/command/info_subcmd/file.rb +162 -0
  61. data/processor/command/info_subcmd/frame.rb +39 -0
  62. data/processor/command/info_subcmd/iseq.rb +83 -0
  63. data/processor/command/info_subcmd/locals.rb +88 -0
  64. data/processor/command/info_subcmd/program.rb +54 -0
  65. data/processor/command/info_subcmd/registers.rb +72 -0
  66. data/processor/command/info_subcmd/registers_subcmd/dfp.rb +38 -0
  67. data/processor/command/info_subcmd/registers_subcmd/helper.rb +40 -0
  68. data/processor/command/info_subcmd/registers_subcmd/lfp.rb +54 -0
  69. data/processor/command/info_subcmd/registers_subcmd/pc.rb +44 -0
  70. data/processor/command/info_subcmd/registers_subcmd/sp.rb +75 -0
  71. data/processor/command/info_subcmd/return.rb +40 -0
  72. data/processor/command/info_subcmd/thread.rb +106 -0
  73. data/processor/command/irb.rb +106 -0
  74. data/processor/command/kill.rb +58 -0
  75. data/processor/command/list.rb +327 -0
  76. data/processor/command/macro.rb +65 -0
  77. data/processor/command/next.rb +89 -0
  78. data/processor/command/nocache.rb +33 -0
  79. data/processor/command/print.rb +37 -0
  80. data/processor/command/ps.rb +40 -0
  81. data/processor/command/quit.rb +62 -0
  82. data/processor/command/raise.rb +47 -0
  83. data/processor/command/reload.rb +28 -0
  84. data/processor/command/reload_subcmd/command.rb +34 -0
  85. data/processor/command/restart.rb +57 -0
  86. data/processor/command/save.rb +60 -0
  87. data/processor/command/set.rb +47 -0
  88. data/processor/command/set_subcmd/auto.rb +27 -0
  89. data/processor/command/set_subcmd/auto_subcmd/eval.rb +67 -0
  90. data/processor/command/set_subcmd/auto_subcmd/irb.rb +49 -0
  91. data/processor/command/set_subcmd/auto_subcmd/list.rb +51 -0
  92. data/processor/command/set_subcmd/basename.rb +39 -0
  93. data/processor/command/set_subcmd/debug.rb +27 -0
  94. data/processor/command/set_subcmd/debug_subcmd/dbgr.rb +49 -0
  95. data/processor/command/set_subcmd/debug_subcmd/except.rb +35 -0
  96. data/processor/command/set_subcmd/debug_subcmd/macro.rb +35 -0
  97. data/processor/command/set_subcmd/debug_subcmd/skip.rb +35 -0
  98. data/processor/command/set_subcmd/debug_subcmd/stack.rb +45 -0
  99. data/processor/command/set_subcmd/different.rb +67 -0
  100. data/processor/command/set_subcmd/events.rb +71 -0
  101. data/processor/command/set_subcmd/max.rb +35 -0
  102. data/processor/command/set_subcmd/max_subcmd/list.rb +50 -0
  103. data/processor/command/set_subcmd/max_subcmd/stack.rb +60 -0
  104. data/processor/command/set_subcmd/max_subcmd/string.rb +53 -0
  105. data/processor/command/set_subcmd/max_subcmd/width.rb +50 -0
  106. data/processor/command/set_subcmd/return.rb +66 -0
  107. data/processor/command/set_subcmd/sp.rb +62 -0
  108. data/processor/command/set_subcmd/substitute.rb +25 -0
  109. data/processor/command/set_subcmd/substitute_subcmd/eval.rb +98 -0
  110. data/processor/command/set_subcmd/substitute_subcmd/path.rb +55 -0
  111. data/processor/command/set_subcmd/substitute_subcmd/string.rb +72 -0
  112. data/processor/command/set_subcmd/timer.rb +68 -0
  113. data/processor/command/set_subcmd/trace.rb +43 -0
  114. data/processor/command/set_subcmd/trace_subcmd/buffer.rb +56 -0
  115. data/processor/command/set_subcmd/trace_subcmd/print.rb +54 -0
  116. data/processor/command/set_subcmd/trace_subcmd/var.rb +61 -0
  117. data/processor/command/show.rb +27 -0
  118. data/processor/command/show_subcmd/alias.rb +50 -0
  119. data/processor/command/show_subcmd/args.rb +50 -0
  120. data/processor/command/show_subcmd/auto.rb +27 -0
  121. data/processor/command/show_subcmd/auto_subcmd/eval.rb +38 -0
  122. data/processor/command/show_subcmd/auto_subcmd/irb.rb +34 -0
  123. data/processor/command/show_subcmd/auto_subcmd/list.rb +36 -0
  124. data/processor/command/show_subcmd/basename.rb +28 -0
  125. data/processor/command/show_subcmd/debug.rb +27 -0
  126. data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +31 -0
  127. data/processor/command/show_subcmd/debug_subcmd/except.rb +33 -0
  128. data/processor/command/show_subcmd/debug_subcmd/macro.rb +32 -0
  129. data/processor/command/show_subcmd/debug_subcmd/skip.rb +33 -0
  130. data/processor/command/show_subcmd/debug_subcmd/stack.rb +32 -0
  131. data/processor/command/show_subcmd/different.rb +37 -0
  132. data/processor/command/show_subcmd/events.rb +40 -0
  133. data/processor/command/show_subcmd/macro.rb +45 -0
  134. data/processor/command/show_subcmd/max.rb +31 -0
  135. data/processor/command/show_subcmd/max_subcmd/list.rb +39 -0
  136. data/processor/command/show_subcmd/max_subcmd/stack.rb +35 -0
  137. data/processor/command/show_subcmd/max_subcmd/string.rb +41 -0
  138. data/processor/command/show_subcmd/max_subcmd/width.rb +36 -0
  139. data/processor/command/show_subcmd/trace.rb +29 -0
  140. data/processor/command/show_subcmd/trace_subcmd/buffer.rb +84 -0
  141. data/processor/command/show_subcmd/trace_subcmd/print.rb +38 -0
  142. data/processor/command/source.rb +74 -0
  143. data/processor/command/step.rb +139 -0
  144. data/processor/command/stepi.rb +63 -0
  145. data/processor/command/unalias.rb +44 -0
  146. data/processor/command/undisplay.rb +63 -0
  147. data/processor/command/up.rb +92 -0
  148. data/processor/default.rb +45 -0
  149. data/processor/display.rb +17 -0
  150. data/processor/eval.rb +88 -0
  151. data/processor/eventbuf.rb +131 -0
  152. data/processor/frame.rb +230 -0
  153. data/processor/help.rb +72 -0
  154. data/processor/hook.rb +128 -0
  155. data/processor/load_cmds.rb +102 -0
  156. data/processor/location.rb +126 -0
  157. data/processor/main.rb +364 -0
  158. data/processor/mock.rb +100 -0
  159. data/processor/msg.rb +26 -0
  160. data/processor/running.rb +170 -0
  161. data/processor/subcmd.rb +159 -0
  162. data/processor/validate.rb +395 -0
  163. data/test/example/fname with blank.rb +1 -0
  164. data/test/example/gcd-xx.rb +18 -0
  165. data/test/example/gcd.rb +19 -0
  166. data/test/example/gcd1.rb +24 -0
  167. data/test/example/null.rb +1 -0
  168. data/test/example/thread1.rb +3 -0
  169. data/test/functional/fn_helper.rb +119 -0
  170. data/test/functional/test-break.rb +87 -0
  171. data/test/functional/test-condition.rb +59 -0
  172. data/test/functional/test-debugger-call-bug.rb +31 -0
  173. data/test/functional/test-delete.rb +71 -0
  174. data/test/functional/test-finish.rb +44 -0
  175. data/test/functional/test-immediate-step-bug.rb +35 -0
  176. data/test/functional/test-next.rb +77 -0
  177. data/test/functional/test-raise.rb +73 -0
  178. data/test/functional/test-return.rb +100 -0
  179. data/test/functional/test-step.rb +274 -0
  180. data/test/functional/test-stepbug.rb +40 -0
  181. data/test/functional/test-trace-var.rb +40 -0
  182. data/test/functional/tmp/b1.rb +5 -0
  183. data/test/functional/tmp/s1.rb +9 -0
  184. data/test/functional/tmp/t2.rb +6 -0
  185. data/test/integration/file-diff.rb +88 -0
  186. data/test/integration/helper.rb +52 -0
  187. data/test/integration/test-fname-with-blank.rb +11 -0
  188. data/test/integration/test-quit.rb +11 -0
  189. data/test/integration/try-test-enable.rb +11 -0
  190. data/test/unit/cmd-helper.rb +44 -0
  191. data/test/unit/test-app-brkpt.rb +30 -0
  192. data/test/unit/test-app-brkptmgr.rb +56 -0
  193. data/test/unit/test-app-disassemble.rb +60 -0
  194. data/test/unit/test-app-file.rb +46 -0
  195. data/test/unit/test-app-frame.rb +49 -0
  196. data/test/unit/test-app-options.rb +60 -0
  197. data/test/unit/test-app-run.rb +19 -0
  198. data/test/unit/test-app-thread.rb +25 -0
  199. data/test/unit/test-app-util.rb +17 -0
  200. data/test/unit/test-base-subcmd.rb +59 -0
  201. data/test/unit/test-bin-trepan.rb +48 -0
  202. data/test/unit/test-cmd-alias.rb +50 -0
  203. data/test/unit/test-cmd-break.rb +80 -0
  204. data/test/unit/test-cmd-endisable.rb +59 -0
  205. data/test/unit/test-cmd-help.rb +100 -0
  206. data/test/unit/test-cmd-kill.rb +47 -0
  207. data/test/unit/test-cmd-quit.rb +26 -0
  208. data/test/unit/test-cmd-step.rb +45 -0
  209. data/test/unit/test-intf-user.rb +45 -0
  210. data/test/unit/test-io-input.rb +26 -0
  211. data/test/unit/test-proc-eval.rb +26 -0
  212. data/test/unit/test-proc-frame.rb +77 -0
  213. data/test/unit/test-proc-help.rb +15 -0
  214. data/test/unit/test-proc-hook.rb +29 -0
  215. data/test/unit/test-proc-load_cmds.rb +40 -0
  216. data/test/unit/test-proc-main.rb +99 -0
  217. data/test/unit/test-proc-validate.rb +90 -0
  218. data/test/unit/test-subcmd-help.rb +48 -0
  219. metadata +358 -0
@@ -0,0 +1,327 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # -*- coding: utf-8 -*-
3
+ require 'linecache'
4
+ require_relative 'base/cmd'
5
+
6
+ class Trepan::Command::ListCommand < Trepan::Command
7
+ unless defined?(HELP)
8
+ HELP =
9
+ "list[>] [MODULE] [FIRST [NUM]]
10
+ list[>] LOCATION [NUM]
11
+
12
+ List source code.
13
+
14
+ Without arguments, prints lines centered around the current
15
+ line. If this is the first list command issued since the debugger
16
+ command loop was entered, then the current line is the current
17
+ frame. If a subsequent list command was issued with no intervening
18
+ frame changing, then that is start the line after we last one
19
+ previously shown.
20
+
21
+ If the command has a '>' suffix, then lines centering is disabled and
22
+ listing begins at the specificed location.
23
+
24
+ The number of line to show is controled by the debugger listsize
25
+ setting. Use 'set listsize' or 'show listsize' to see or set the
26
+ value.
27
+
28
+ \"list -\" shows lines before a previous listing.
29
+
30
+ A LOCATION is a either
31
+ - number, e.g. 5,
32
+ - a function, e.g. join or os.path.join
33
+ - a module, e.g. os or os.path
34
+ - a filename, colon, and a number, e.g. foo.rb:5,
35
+ - or a module name and a number, e.g,. os.path:5.
36
+ - a '.' for the current line number
37
+ - a '-' for the lines before the current line number
38
+
39
+ If the location form is used with a subsequent parameter, the
40
+ parameter is the starting line number. When there two numbers are
41
+ given, the last number value is treated as a stopping line unless it
42
+ is less than the start line, in which case it is taken to mean the
43
+ number of lines to list instead.
44
+
45
+ Wherever a number is expected, it does not need to be a constant --
46
+ just something that evaluates to a positive integer.
47
+
48
+ Some examples:
49
+
50
+ list 5 # List centered around line 5
51
+ list 4+1 # Same as above.
52
+ list 5> # List starting at line 5
53
+ list foo.rb:5 # List centered around line 5 of foo.rb
54
+ list foo.rb 5 # Same as above.
55
+ list foo.rb:5> # List starting around line 5 of foo.rb
56
+ list foo.rb 5 6 # list lines 5 and 6 of foo.rb
57
+ list foo.rb 5 2 # Same as above, since 2 < 5.
58
+ list foo.rb:5 2 # Same as above
59
+ list FileUtils.cp # List lines around the FileUtils.cp function.
60
+ list . # List lines centered from where we currently are stopped
61
+ list - # List lines previous to those just shown
62
+
63
+ The output of the list command give a line number, and some status
64
+ information about the line and the text of the line. Here is some
65
+ hypothetical list output modeled roughly around line 251 of one
66
+ version of this code:
67
+
68
+ 251 cmd.proc.frame_setup(tf)
69
+ 252 -> brkpt_cmd.run(['break'])
70
+ 253 B01 line = __LINE__
71
+ 254 b02 cmd.run(['list', __LINE__.to_s])
72
+ 255 t03 puts '--' * 10
73
+
74
+ Line 251 has nothing special about it. Line 252 is where we are
75
+ currently stopped. On line 253 there is a breakpoint 1 which is
76
+ enabled, while at line 255 there is an breakpoint 2 which is
77
+ disabled."
78
+
79
+ ALIASES = %w(l list> l>)
80
+ CATEGORY = 'files'
81
+ MAX_ARGS = 3
82
+ NAME = File.basename(__FILE__, '.rb')
83
+ SHORT_HELP = 'List source code'
84
+ end
85
+
86
+ # What a f*cking mess. Necessitated I suppose because we want to
87
+ # allow somewhat flexible parsing with either module names, files or none
88
+ # and optional line counts or end-line numbers.
89
+
90
+ # Parses arguments for the "list" command and returns the tuple:
91
+ # filename, start, last
92
+ # or sets these to nil if there was some problem.
93
+ def parse_list_cmd(args, listsize, center_correction)
94
+
95
+ frame = @proc.frame
96
+
97
+ container = @proc.frame_container(frame, false)
98
+
99
+ # FIXME: put into a helper routine
100
+ # See also duplicate code in print_location
101
+ if container[0] != 'file'
102
+ try_container = container
103
+ while try_container[0] != 'file' && frame.prev do
104
+ frame = frame.prev
105
+ try_container = @proc.frame_container(frame, false)
106
+ end
107
+ container = try_container if try_container[0] == 'file'
108
+ end
109
+
110
+ filename = container[1]
111
+
112
+ last = nil
113
+ if args.empty? and not frame
114
+ errmsg("No Ruby program loaded.")
115
+ return nil, nil, nil
116
+ end
117
+
118
+ if args.size > 0
119
+ if args[0] == '-'
120
+ return no_frame_msg unless @proc.line_no
121
+ first = [1, @proc.line_no - 2*listsize - 1].max
122
+ elsif args[0] == '.'
123
+ return no_frame_msg unless @proc.line_no
124
+ first = [1, @proc.frame_line - center_correction].max
125
+ else
126
+ modfunc, container, first = @proc.parse_position(args[0])
127
+ if first == nil and modfunc == nil
128
+ # error should have been shown previously
129
+ return nil, nil, nil
130
+ end
131
+ if args.size == 1
132
+ first = 1 if !first and modfunc
133
+ first = [1, first - center_correction].max
134
+ elsif args.size == 2 or (args.size == 3 and modfunc)
135
+ opts = {
136
+ :msg_on_error =>
137
+ 'Starting line expected, got %s.' % args[-1]
138
+ }
139
+ num = @proc.get_an_int(args[1], opts)
140
+
141
+ return nil, nil, nil unless num
142
+ if modfunc
143
+ if first
144
+ first = num
145
+ if args.size == 3 and modfunc
146
+ opts[:msg_on_error] = ('last or count parameter expected, ' +
147
+ 'got: %s.' % args[2])
148
+ last = @proc.get_an_int(args[2], opts)
149
+ end
150
+ else
151
+ last = num
152
+ end
153
+ else
154
+ first = num - center_correction
155
+ end
156
+ if last and last < first
157
+ # Assume last is a count rather than an end line number
158
+ last = first + last - 1
159
+ end
160
+ elsif not modfunc
161
+ errmsg('At most 2 parameters allowed when no module' +
162
+ ' name is found/given. Saw: %d parameters' % args.size)
163
+ return nil, nil, nil
164
+ else
165
+ errmsg(('At most 3 parameters allowed when a module' +
166
+ ' name is given. Saw: %d parameters') % args.size)
167
+ return nil, nil, nil
168
+ end
169
+ end
170
+ elsif !@proc.line_no and frame
171
+ first = [1, @proc.frame_line - center_correction].max
172
+ else
173
+ first = [1, @proc.line_no - center_correction].max
174
+ end
175
+ last = first + listsize - 1 unless last
176
+
177
+ LineCache::cache(container[1]) unless
178
+ 'file' != container[0] || LineCache::cached?(container[1])
179
+ return container, first, last
180
+ end
181
+
182
+ def no_frame_msg
183
+ errmsg("No Ruby program loaded.")
184
+ return nil, nil, nil
185
+ end
186
+
187
+ def run(args)
188
+ listsize = settings[:maxlist]
189
+ center_correction =
190
+ if args[0][-1..-1] == '>'
191
+ 0
192
+ else
193
+ (listsize-1) / 2
194
+ end
195
+
196
+ container, first, last =
197
+ parse_list_cmd(args[1..-1], listsize, center_correction)
198
+ frame = @proc.frame
199
+ return unless container
200
+ breaklist = @proc.brkpts.line_breaks(container)
201
+
202
+ # We now have range information. Do the listing.
203
+ max_line = LineCache::size(container[1])
204
+ unless max_line
205
+ errmsg('File "%s" not found.' % container[1])
206
+ return
207
+ end
208
+
209
+ if first > max_line
210
+ errmsg('Bad line range [%d...%d]; file "%s" has only %d lines' %
211
+ [first, last, container[1], max_line])
212
+ return
213
+ end
214
+
215
+ if last > max_line
216
+ # msg('End position changed to last line %d ' % max_line)
217
+ last = max_line
218
+ end
219
+
220
+ begin
221
+ first.upto(last).each do |lineno|
222
+ line = LineCache::getline(container[1], lineno,
223
+ @proc.reload_on_change).chomp
224
+ unless line
225
+ msg('[EOF]')
226
+ break
227
+ end
228
+ s = '%3d' % lineno
229
+ s = s + ' ' if s.size < 4
230
+ s += if breaklist.member?(lineno)
231
+ bp = breaklist[lineno]
232
+ a_pad = '%02d' % bp.id
233
+ bp.icon_char
234
+ else
235
+ a_pad = ' '
236
+ ' '
237
+ end
238
+ s += (frame && lineno == @proc.frame_line &&
239
+ container == frame.source_container) ? '->' : a_pad
240
+ msg(s + "\t" + line)
241
+ @proc.line_no = lineno
242
+ end
243
+ rescue => e
244
+ errmsg e if settings[:debugexcept]
245
+ end
246
+ end
247
+ end
248
+
249
+ if __FILE__ == $0
250
+ if not (ARGV.size == 1 && ARGV[0] == 'noload')
251
+ ISEQS__ = {}
252
+ SCRIPT_ISEQS__ = {}
253
+ ARGV[0..-1] = ['noload']
254
+ load(__FILE__)
255
+ else
256
+ require_relative '../location'
257
+ require_relative '../mock'
258
+ require_relative '../frame'
259
+ name = File.basename(__FILE__, '.rb')
260
+ dbgr, cmd = MockDebugger::setup(name)
261
+ cmd.proc.send('frame_initialize')
262
+ LineCache::cache(__FILE__)
263
+ cmd.run(['list'])
264
+ cmd.run(['list', __FILE__ + ':10'])
265
+
266
+ def run_cmd(cmd, args)
267
+ seps = '--' * 10
268
+ puts "%s %s %s" % [seps, args.join(' '), seps]
269
+ cmd.run(args)
270
+ end
271
+
272
+
273
+ load 'tmpdir.rb'
274
+ run_cmd(cmd, %w(list tmpdir.rb 10))
275
+ run_cmd(cmd, %w(list tmpdir.rb))
276
+
277
+ # cmd.proc.frame = sys._getframe()
278
+ # cmd.proc.setup()
279
+ # cmd.run(['list'])
280
+
281
+ run_cmd(cmd, %w(list .))
282
+ run_cmd(cmd, %w(list 30))
283
+
284
+ # cmd.run(['list', '9+1'])
285
+
286
+ run_cmd(cmd, %w(list> 10))
287
+ run_cmd(cmd, %w(list 3000))
288
+ run_cmd(cmd, %w(list run_cmd))
289
+
290
+ p = Proc.new do
291
+ |x,y| x + y
292
+ end
293
+ run_cmd(cmd, %w(list p))
294
+
295
+ # Function from a file found via an instruction sequence
296
+ run_cmd(cmd, %w(list Columnize.columnize))
297
+
298
+ # Use Class/method name. 15 isn't in the function - should this be okay?
299
+ run_cmd(cmd, %w(list Columnize.columnize 15))
300
+
301
+ # Start line and count, since 3 < 30
302
+ run_cmd(cmd, %w(list Columnize.columnize 30 3))
303
+
304
+ # Start line finish line
305
+ run_cmd(cmd, %w(list Columnize.columnize 40 50))
306
+
307
+ # puts '--' * 10
308
+ # cmd.run(['list', os.path.abspath(__file__)+':3', '4'])
309
+ # puts '--' * 10
310
+ # cmd.run(['list', os.path.abspath(__file__)+':3', '12-10'])
311
+ # cmd.run(['list', 'os.path:5'])
312
+
313
+ require 'thread_frame'
314
+ tf = RubyVM::ThreadFrame.current
315
+ cmd.proc.frame_setup(tf)
316
+ brkpt_cmd = cmd.proc.instance_variable_get('@commands')['break']
317
+ brkpt_cmd.run(['break'])
318
+ line = __LINE__
319
+ run_cmd(cmd, ['list', __LINE__.to_s])
320
+
321
+ disable_cmd = cmd.proc.instance_variable_get('@commands')['disable']
322
+ disable_cmd.run(['disable', '1'])
323
+
324
+ run_cmd(cmd, ['list', line.to_s])
325
+ run_cmd(cmd, %w(list parse_list_cmd))
326
+ end
327
+ end
@@ -0,0 +1,65 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'base/cmd'
4
+ require_relative '../eval'
5
+ class Trepan::Command::MacroCommand < Trepan::Command
6
+
7
+ unless defined?(HELP)
8
+ HELP =
9
+ "macro NAME PROC-OBJECT
10
+
11
+ Define NAME as a debugger macro. Debugger macros get a list of arguments
12
+ and should return a command string to use in its place.
13
+
14
+ Here is a contrived example that shows how to issue 'finish' if we are in
15
+ method 'gcd' and 'step' otherwise:
16
+
17
+ macro step_unless_gcd Proc.new{|*args| \"$trepan_frame.method == 'gcd' ? 'finish' : 'step'\"}
18
+
19
+ Here is another real example. I use the following to debug a
20
+ debugger command, assuming 'set debug dbgr' is set:
21
+
22
+ macro dbgcmd Proc.new{|*args| \"debug $trepan_cmdproc.commands['\#{args[0]}'].run(\#{args.inspect})\"}
23
+
24
+ With the above, 'dbgcmd list 5' will debug the debugger 'list' command
25
+ on the command 'list 5'.
26
+
27
+ See also 'show macro'.
28
+ "
29
+
30
+ CATEGORY = 'support'
31
+ MIN_ARGS = 2 # Need at least this many
32
+ NAME = File.basename(__FILE__, '.rb')
33
+ SHORT_HELP = 'Define a macro'
34
+ end
35
+
36
+ def run(args)
37
+ macro_name = args[1]
38
+ proc_argstr = @proc.cmd_argstr[macro_name.size..-1].lstrip
39
+ proc_obj = @proc.debug_eval(proc_argstr, @proc.settings[:maxstring])
40
+ if proc_obj
41
+ if proc_obj.is_a?(Proc)
42
+ @proc.macros[macro_name] = proc_obj
43
+ msg "Macro \"#{macro_name}\" defined."
44
+ else
45
+ errmsg "Expecting a Proc object; got: #{proc_argstr}"
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ if __FILE__ == $0
52
+ require_relative '../mock'
53
+ name = File.basename(__FILE__, '.rb')
54
+ dbgr, cmd = MockDebugger::setup(name)
55
+ cmdproc = dbgr.core.processor
56
+ ['macro foo Proc.new{|x, y| x+y}',
57
+ 'macro bad x+1',
58
+ 'macro bad2 1+2'].each do |cmdline|
59
+ args = cmdline.split
60
+ cmd_argstr = cmdline[args[0].size..-1].lstrip
61
+ cmdproc.instance_variable_set('@cmd_argstr', cmd_argstr)
62
+ cmd.run(args)
63
+ end
64
+ p cmdproc.macros
65
+ end
@@ -0,0 +1,89 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'base/cmd'
4
+
5
+ class Trepan::Command::NextCommand < Trepan::Command
6
+
7
+ unless defined?(HELP)
8
+ HELP =
9
+ "next[+|=|-|<|>|!|<>] [EVENT-NAME...] [count]
10
+
11
+ Step one statement ignoring steps into function calls at this level.
12
+ Sometimes this is called 'step over'.
13
+
14
+ With an integer argument, perform 'next' that many times. However if
15
+ an exception occurs at this level, or we 'return' or 'yield' or the
16
+ thread changes, we stop regardless of count.
17
+
18
+ A suffix of '+' on the command or an alias to the command forces to
19
+ move to another line, while a suffix of '-' does the opposite and
20
+ disables the requiring a move to a new line. If no suffix is given,
21
+ the debugger setting 'different' determines this behavior.
22
+
23
+ If no suffix is given, the debugger setting 'different'
24
+ determines this behavior.
25
+
26
+ Examples:
27
+ next # next 1 event, *any* event
28
+ next 1 # same as above
29
+ next+ # same but force stopping on a new line
30
+ next= # same but force stopping on a new line a new frame added
31
+ next- # same but force stopping on a new line a new frame added
32
+ next 5/5+0 # same as above
33
+ next line # next using only line events
34
+ next call # next using only call call events
35
+ next<> # next using call return events at this level or below
36
+ "
37
+
38
+ ALIASES = %w(n next+ next- next< next> next<> next! n> n< n! n+ n-
39
+ n<> n=)
40
+ CATEGORY = 'running'
41
+ # execution_set = ['Running']
42
+ MAX_ARGS = 1 # Need at most this many. FIXME: will be eventually 2
43
+ NAME = File.basename(__FILE__, '.rb')
44
+ NEED_RUNNING = true
45
+ SHORT_HELP = 'Step program without entering called functions'
46
+ end
47
+
48
+ # This method runs the command
49
+ def run(args) # :nodoc
50
+ opts = @proc.parse_next_step_suffix(args[0])
51
+ if args.size == 1
52
+ # Form is: "next" which means "next 1"
53
+ step_count = 0
54
+ else
55
+ count_str = args[1]
56
+ opts = {
57
+ :msg_on_error =>
58
+ "The 'next' command argument must eval to an integer. Got: %s" %
59
+ count_str,
60
+ :min_value => 1
61
+ }
62
+ count = @proc.get_an_int(count_str, opts)
63
+ return unless count
64
+ # step 1 is core.step_count = 0 or "stop next event"
65
+ step_count = count - 1
66
+ end
67
+ @proc.next(step_count, opts)
68
+ end
69
+ end
70
+
71
+ if __FILE__ == $0
72
+ require_relative '../mock'
73
+ name = File.basename(__FILE__, '.rb')
74
+ dbgr, cmd = MockDebugger::setup(name)
75
+ [%w(n 5), %w(next 1+2), %w(n foo)].each do |c|
76
+ dbgr.core.step_count = 0
77
+ cmd.proc.leave_cmd_loop = false
78
+ result = cmd.run(c)
79
+ puts 'Run result: %s' % result
80
+ puts 'step_count %d, leave_cmd_loop: %s' % [dbgr.core.step_count,
81
+ cmd.proc.leave_cmd_loop]
82
+ end
83
+ [%w(n), %w(next+), %w(n-)].each do |c|
84
+ dbgr.core.step_count = 0
85
+ cmd.proc.leave_cmd_loop = false
86
+ result = cmd.run(c)
87
+ puts cmd.proc.different_pos
88
+ end
89
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'base/cmd'
4
+ class Trepan::Command::NoCacheCommand < Trepan::Command
5
+
6
+ unless defined?(HELP)
7
+ HELP = "Remove getinlinecache instructions from instruction sequence."
8
+
9
+ CATEGORY = 'running'
10
+ MAX_ARGS = 0 # Need at most this many
11
+ NAME = File.basename(__FILE__, '.rb')
12
+ NEED_STACK = true
13
+ SHORT_HELP = 'Remove getinlinecache instructions from instruction sequence.'
14
+
15
+ end
16
+
17
+ # This method runs the command
18
+ def run(args) # :nodoc
19
+ if @proc.frame.iseq
20
+ puts @proc.frame.iseq.disassemble
21
+ count = @proc.frame.iseq.killcache
22
+ msg ("%d locations removed" % count)
23
+ # puts @proc.frame.iseq.disassemble
24
+ end
25
+ end
26
+ end
27
+
28
+ if __FILE__ == $0
29
+ require_relative '../mock'
30
+ name = File.basename(__FILE__, '.rb')
31
+ dbgr, cmd = MockDebugger::setup(name)
32
+ cmd.run([name])
33
+ end
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'base/cmd'
4
+ require_relative '../eval'
5
+ class Trepan::Command::PrintCommand < Trepan::Command
6
+
7
+ unless defined?(HELP)
8
+ HELP =
9
+ "print EXPRESSION
10
+
11
+ Print the value of the EXPRESSION. Variables accessible are those of the
12
+ environment of the selected stack frame, plus globals.
13
+
14
+ If the length output string large, the first part of the value is
15
+ shown and ... indicates it has been truncated."
16
+
17
+ # ALIASES = %w(p)
18
+ CATEGORY = 'data'
19
+ NAME = File.basename(__FILE__, '.rb')
20
+ SHORT_HELP = 'Print expression'
21
+ end
22
+
23
+ def run(args)
24
+ msg @proc.debug_eval(@proc.cmd_argstr, @proc.settings[:maxstring])
25
+ end
26
+ end
27
+
28
+ if __FILE__ == $0
29
+ require_relative '../mock'
30
+ name = File.basename(__FILE__, '.rb')
31
+ dbgr, cmd = MockDebugger::setup(name)
32
+ arg_str = '1 + 2'
33
+ cmd.proc.instance_variable_set('@cmd_argstr', arg_str)
34
+ cmd.run([name, arg_str])
35
+ cmdproc = dbgr.core.processor
36
+ cmds = dbgr.core.processor.commands
37
+ end
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'base/cmd'
4
+ require_relative '../eval'
5
+ class Trepan::Command::PsCommand < Trepan::Command
6
+
7
+ unless defined?(HELP)
8
+ HELP =
9
+ "ps ARRAY
10
+
11
+ Print the value of the ARRAY in columns and sorted."
12
+
13
+ CATEGORY = 'data'
14
+ MIN_ARGS = 1 # Need least this many
15
+ NAME = File.basename(__FILE__, '.rb')
16
+ SHORT_HELP = 'Print array sorted and in columns'
17
+ end
18
+
19
+ def run(args)
20
+ array = @proc.debug_eval(@proc.cmd_argstr, @proc.settings[:maxstring])
21
+ # FIXME: should test for enumerable
22
+ if array.is_a?(Array)
23
+ msg columnize_commands(array.sort)
24
+ else
25
+ errmsg "ps: #{@proc.cmd_argstr} should evaluate an Array not #{array.class}"
26
+ end
27
+ end
28
+ end
29
+
30
+ if __FILE__ == $0
31
+ require_relative '../mock'
32
+ name = File.basename(__FILE__, '.rb')
33
+ dbgr, cmd = MockDebugger::setup(name)
34
+ arg_str = '(1..30).to_a'
35
+ cmd.proc.instance_variable_set('@cmd_argstr', arg_str)
36
+ cmd.run([name, arg_str])
37
+ arg_str = '1'
38
+ cmd.proc.instance_variable_set('@cmd_argstr', arg_str)
39
+ cmd.run([name, arg_str])
40
+ end
@@ -0,0 +1,62 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require_relative 'base/cmd'
3
+ class Trepan::Command::QuitCommand < Trepan::Command
4
+
5
+ unless defined?(HELP)
6
+ HELP =
7
+ 'quit[!] [unconditionally] [exit code] - gentle termination
8
+
9
+ The program being debugged is exited via exit() which runs the Kernel
10
+ at_exit finalizers. If a return code is given, that is the return code
11
+ passed to exit() - presumably the return code that will be passed back
12
+ to the OS. If no exit code is given, 0 is used.
13
+
14
+ Examples:
15
+ quit # quit prompting if we are interactive
16
+ quit conditionally # quit without prompting
17
+ quit! # same as above
18
+ quit 0 # same as "quit"
19
+ quit! 1 # unconditional quit setting exit code 1
20
+
21
+ See also the commands "exit" and "kill".'
22
+
23
+ ALIASES = %w(quit! q q!)
24
+ CATEGORY = 'support'
25
+ NAME = File.basename(__FILE__, '.rb')
26
+ MAX_ARGS = 2 # Need at most this many
27
+ SHORT_HELP = 'Quit program - gently'
28
+ end
29
+
30
+ # FIXME: Combine 'quit' and 'exit'. The only difference is
31
+ # whether exit! or exit is used.
32
+
33
+ # This method runs the command
34
+ def run(args) # :nodoc
35
+ unconditional =
36
+ if args.size > 1 && args[1] == 'unconditionally'
37
+ args.shift
38
+ true
39
+ elsif args[0][-1] == '!'
40
+ true
41
+ else
42
+ false
43
+ end
44
+ unless unconditional || confirm('Really quit?', false)
45
+ msg('Quit not confirmed.')
46
+ return
47
+ end
48
+
49
+ exitrc = (args.size > 1) ? exitrc = Integer(args[1]) rescue 0 : 0
50
+ # No graceful way to stop threads...
51
+ exit exitrc
52
+ end
53
+ end
54
+
55
+ if __FILE__ == $0
56
+ require_relative '../mock'
57
+ name = File.basename(__FILE__, '.rb')
58
+ dbgr, cmd = MockDebugger::setup(name)
59
+ name = File.basename(__FILE__, '.rb')
60
+ fork { cmd.run([name]) }
61
+ cmd.run([name, '5'])
62
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require_relative 'base/cmd'
3
+ class Trepan::Command::RaiseCommand < Trepan::Command
4
+
5
+ unless defined?(HELP)
6
+ HELP =
7
+ "raise EXCEPTION
8
+
9
+ Raise an exception in the debugged program."
10
+
11
+ CATEGORY = 'running'
12
+ MAX_ARGS = 1 # Need at most this many
13
+ NAME = File.basename(__FILE__, '.rb')
14
+ SHORT_HELP = 'Raise an exception in the debugged program'
15
+ end
16
+
17
+ # This method runs the command
18
+ def run(args) # :nodoc
19
+ exception =
20
+ if args.size > 1
21
+ except_str = args[1..-1].join(' ')
22
+ # Normally would need x.respond_to? && ..
23
+ # but since we catch errors with debug_eval.. not needed.
24
+ eval_str = ("%s.ancestors.include?(Exception)" %
25
+ [except_str])
26
+ unless @proc.debug_eval_no_errmsg(eval_str)
27
+ errmsg "\"#{except_str}\" does not inherit Exception."
28
+ return
29
+ end
30
+ @proc.debug_eval_no_errmsg(except_str)
31
+ else
32
+ RuntimeError
33
+ end
34
+ @proc.step(0)
35
+ @proc.leave_cmd_loop = true
36
+ @proc.core.exception = exception
37
+ end
38
+ end
39
+
40
+ if __FILE__ == $0
41
+ require_relative '../mock'
42
+ name = File.basename(__FILE__, '.rb')
43
+ dbgr, cmd = MockDebugger::setup(name)
44
+ puts cmd.run([name, 'NotanException'])
45
+ puts cmd.run([name, '[5]'])
46
+ puts cmd.run([name, 'RuntimeError'])
47
+ end