debugger2 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +3 -0
  4. data/AUTHORS +10 -0
  5. data/CHANGELOG.md +65 -0
  6. data/CONTRIBUTING.md +1 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +23 -0
  9. data/OLDER_CHANGELOG +334 -0
  10. data/OLD_CHANGELOG +5655 -0
  11. data/OLD_README +122 -0
  12. data/README.md +108 -0
  13. data/Rakefile +78 -0
  14. data/bin/rdebug +397 -0
  15. data/debugger2.gemspec +29 -0
  16. data/doc/.cvsignore +42 -0
  17. data/doc/Makefile.am +63 -0
  18. data/doc/emacs-notes.txt +38 -0
  19. data/doc/hanoi.rb +35 -0
  20. data/doc/primes.rb +28 -0
  21. data/doc/rdebug-emacs.texi +1030 -0
  22. data/doc/ruby-debug.texi +3791 -0
  23. data/doc/test-tri2.rb +18 -0
  24. data/doc/tri3.rb +8 -0
  25. data/doc/triangle.rb +12 -0
  26. data/emacs/Makefile.am +130 -0
  27. data/emacs/rdebug-annotate.el +385 -0
  28. data/emacs/rdebug-breaks.el +407 -0
  29. data/emacs/rdebug-cmd.el +92 -0
  30. data/emacs/rdebug-core.el +502 -0
  31. data/emacs/rdebug-dbg.el +62 -0
  32. data/emacs/rdebug-error.el +79 -0
  33. data/emacs/rdebug-fns.el +111 -0
  34. data/emacs/rdebug-frames.el +230 -0
  35. data/emacs/rdebug-gud.el +242 -0
  36. data/emacs/rdebug-help.el +104 -0
  37. data/emacs/rdebug-info.el +83 -0
  38. data/emacs/rdebug-layouts.el +180 -0
  39. data/emacs/rdebug-locring.el +118 -0
  40. data/emacs/rdebug-output.el +106 -0
  41. data/emacs/rdebug-regexp.el +118 -0
  42. data/emacs/rdebug-secondary.el +260 -0
  43. data/emacs/rdebug-shortkey.el +175 -0
  44. data/emacs/rdebug-source.el +568 -0
  45. data/emacs/rdebug-track.el +392 -0
  46. data/emacs/rdebug-varbuf.el +150 -0
  47. data/emacs/rdebug-vars.el +125 -0
  48. data/emacs/rdebug-watch.el +132 -0
  49. data/emacs/rdebug.el +326 -0
  50. data/emacs/test/elk-test.el +242 -0
  51. data/emacs/test/test-annotate.el +103 -0
  52. data/emacs/test/test-cmd.el +116 -0
  53. data/emacs/test/test-core.el +104 -0
  54. data/emacs/test/test-fns.el +65 -0
  55. data/emacs/test/test-frames.el +62 -0
  56. data/emacs/test/test-gud.el +35 -0
  57. data/emacs/test/test-indent.el +58 -0
  58. data/emacs/test/test-regexp.el +144 -0
  59. data/emacs/test/test-shortkey.el +61 -0
  60. data/ext/ruby_debug/breakpoint.c +630 -0
  61. data/ext/ruby_debug/extconf.rb +11 -0
  62. data/ext/ruby_debug/ruby_debug.c +2203 -0
  63. data/ext/ruby_debug/ruby_debug.h +151 -0
  64. data/lib/debugger.rb +5 -0
  65. data/lib/debugger/version.rb +5 -0
  66. data/lib/debugger2.rb +6 -0
  67. data/lib/ruby-debug-base.rb +307 -0
  68. data/lib/ruby-debug.rb +176 -0
  69. data/lib/ruby-debug/command.rb +227 -0
  70. data/lib/ruby-debug/commands/breakpoints.rb +153 -0
  71. data/lib/ruby-debug/commands/catchpoint.rb +55 -0
  72. data/lib/ruby-debug/commands/condition.rb +49 -0
  73. data/lib/ruby-debug/commands/continue.rb +38 -0
  74. data/lib/ruby-debug/commands/control.rb +107 -0
  75. data/lib/ruby-debug/commands/display.rb +120 -0
  76. data/lib/ruby-debug/commands/edit.rb +48 -0
  77. data/lib/ruby-debug/commands/enable.rb +202 -0
  78. data/lib/ruby-debug/commands/eval.rb +176 -0
  79. data/lib/ruby-debug/commands/finish.rb +42 -0
  80. data/lib/ruby-debug/commands/frame.rb +301 -0
  81. data/lib/ruby-debug/commands/help.rb +56 -0
  82. data/lib/ruby-debug/commands/info.rb +467 -0
  83. data/lib/ruby-debug/commands/irb.rb +123 -0
  84. data/lib/ruby-debug/commands/jump.rb +66 -0
  85. data/lib/ruby-debug/commands/kill.rb +51 -0
  86. data/lib/ruby-debug/commands/list.rb +94 -0
  87. data/lib/ruby-debug/commands/method.rb +84 -0
  88. data/lib/ruby-debug/commands/quit.rb +39 -0
  89. data/lib/ruby-debug/commands/reload.rb +40 -0
  90. data/lib/ruby-debug/commands/save.rb +90 -0
  91. data/lib/ruby-debug/commands/set.rb +223 -0
  92. data/lib/ruby-debug/commands/show.rb +247 -0
  93. data/lib/ruby-debug/commands/skip.rb +35 -0
  94. data/lib/ruby-debug/commands/source.rb +36 -0
  95. data/lib/ruby-debug/commands/stepping.rb +81 -0
  96. data/lib/ruby-debug/commands/threads.rb +189 -0
  97. data/lib/ruby-debug/commands/tmate.rb +36 -0
  98. data/lib/ruby-debug/commands/trace.rb +57 -0
  99. data/lib/ruby-debug/commands/variables.rb +199 -0
  100. data/lib/ruby-debug/debugger.rb +5 -0
  101. data/lib/ruby-debug/helper.rb +69 -0
  102. data/lib/ruby-debug/interface.rb +232 -0
  103. data/lib/ruby-debug/processor.rb +474 -0
  104. data/man/rdebug.1 +241 -0
  105. data/old_scripts/Makefile.am +14 -0
  106. data/old_scripts/README.md +2 -0
  107. data/old_scripts/autogen.sh +4 -0
  108. data/old_scripts/configure.ac +12 -0
  109. data/old_scripts/rdbg.rb +33 -0
  110. data/old_scripts/runner.sh +7 -0
  111. data/old_scripts/svn2cl_usermap +3 -0
  112. data/test/.cvsignore +1 -0
  113. data/test/breakpoints_test.rb +366 -0
  114. data/test/conditions_test.rb +77 -0
  115. data/test/continue_test.rb +28 -0
  116. data/test/display_test.rb +143 -0
  117. data/test/edit_test.rb +55 -0
  118. data/test/eval_test.rb +94 -0
  119. data/test/examples/breakpoint1.rb +15 -0
  120. data/test/examples/breakpoint2.rb +7 -0
  121. data/test/examples/conditions.rb +4 -0
  122. data/test/examples/continue.rb +4 -0
  123. data/test/examples/display.rb +5 -0
  124. data/test/examples/edit.rb +3 -0
  125. data/test/examples/edit2.rb +3 -0
  126. data/test/examples/eval.rb +4 -0
  127. data/test/examples/finish.rb +20 -0
  128. data/test/examples/frame.rb +31 -0
  129. data/test/examples/help.rb +2 -0
  130. data/test/examples/info.rb +48 -0
  131. data/test/examples/info2.rb +3 -0
  132. data/test/examples/irb.rb +6 -0
  133. data/test/examples/jump.rb +14 -0
  134. data/test/examples/kill.rb +2 -0
  135. data/test/examples/list.rb +12 -0
  136. data/test/examples/method.rb +15 -0
  137. data/test/examples/post_mortem.rb +19 -0
  138. data/test/examples/quit.rb +2 -0
  139. data/test/examples/reload.rb +6 -0
  140. data/test/examples/restart.rb +6 -0
  141. data/test/examples/save.rb +3 -0
  142. data/test/examples/set.rb +3 -0
  143. data/test/examples/set_annotate.rb +12 -0
  144. data/test/examples/settings.rb +1 -0
  145. data/test/examples/show.rb +2 -0
  146. data/test/examples/source.rb +3 -0
  147. data/test/examples/stepping.rb +21 -0
  148. data/test/examples/thread.rb +32 -0
  149. data/test/examples/tmate.rb +10 -0
  150. data/test/examples/trace.rb +7 -0
  151. data/test/examples/trace_threads.rb +20 -0
  152. data/test/examples/variables.rb +26 -0
  153. data/test/finish_test.rb +49 -0
  154. data/test/frame_test.rb +140 -0
  155. data/test/help_test.rb +51 -0
  156. data/test/info_test.rb +326 -0
  157. data/test/irb_test.rb +82 -0
  158. data/test/jump_test.rb +70 -0
  159. data/test/kill_test.rb +49 -0
  160. data/test/list_test.rb +147 -0
  161. data/test/method_test.rb +72 -0
  162. data/test/post_mortem_test.rb +25 -0
  163. data/test/quit_test.rb +56 -0
  164. data/test/reload_test.rb +47 -0
  165. data/test/restart_test.rb +145 -0
  166. data/test/save_test.rb +94 -0
  167. data/test/set_test.rb +183 -0
  168. data/test/show_test.rb +294 -0
  169. data/test/source_test.rb +46 -0
  170. data/test/stepping_test.rb +122 -0
  171. data/test/support/breakpoint.rb +12 -0
  172. data/test/support/context.rb +14 -0
  173. data/test/support/matchers.rb +67 -0
  174. data/test/support/mocha_extensions.rb +71 -0
  175. data/test/support/processor.rb +7 -0
  176. data/test/support/test_dsl.rb +206 -0
  177. data/test/support/test_interface.rb +66 -0
  178. data/test/test_helper.rb +9 -0
  179. data/test/thread_test.rb +124 -0
  180. data/test/tmate_test.rb +45 -0
  181. data/test/trace_test.rb +156 -0
  182. data/test/variables_test.rb +116 -0
  183. metadata +319 -0
@@ -0,0 +1,56 @@
1
+ module Debugger
2
+
3
+ # Implements debugger "help" command.
4
+ class HelpCommand < Command
5
+ self.allow_in_control = true
6
+
7
+ def regexp
8
+ /^\s* h(?:elp)? (?:\s+(.+))? $/x
9
+ end
10
+
11
+ def execute
12
+ if @match[1]
13
+ args = @match[1].split
14
+ cmds = @state.commands.select do |cmd|
15
+ [cmd.help_command].flatten.include?(args[0])
16
+ end
17
+ else
18
+ args = @match[1]
19
+ cmds = []
20
+ end
21
+ unless cmds.empty?
22
+ help = cmds.map{ |cmd| cmd.help(args) }.join
23
+ help = help.split("\n").map{|l| l.gsub(/^ +/, '')}
24
+ help.shift if help.first && help.first.empty?
25
+ help.pop if help.last && help.last.empty?
26
+ print help.join("\n")
27
+ else
28
+ if args and args[0]
29
+ errmsg "Undefined command: \"#{args[0]}\". Try \"help\"."
30
+ else
31
+ print "ruby-debug help v#{Debugger::VERSION}\n" unless
32
+ self.class.settings[:debuggertesting]
33
+ print "Type 'help <command-name>' for help on a specific command\n\n"
34
+ print "Available commands:\n"
35
+ cmds = @state.commands.map{ |cmd| cmd.help_command }
36
+ cmds = cmds.flatten.uniq.sort
37
+ print columnize(cmds, self.class.settings[:width])
38
+ end
39
+ end
40
+ print "\n"
41
+ end
42
+
43
+ class << self
44
+ def help_command
45
+ 'help'
46
+ end
47
+
48
+ def help(cmd)
49
+ %{
50
+ h[elp]\t\tprint this help
51
+ h[elp] command\tprint help on command
52
+ }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,467 @@
1
+ module Debugger
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 < Command
23
+ self.allow_in_control = true
24
+ Subcommands =
25
+ [
26
+ ['args', 1, 'Argument variables of current stack frame'],
27
+ ['breakpoints', 1, 'Status of user-settable breakpoints',
28
+ 'Without argument, list info about all breakpoints. With an
29
+ integer argument, list info on that breakpoint.'],
30
+ ['catch', 3, 'Exceptions that can be caught in the current stack frame'],
31
+ ['display', 2, 'Expressions to display when program stops'],
32
+ ['file', 4, 'Info about a particular file read in',
33
+ '
34
+ After the file name is supplied, you can list file attributes that
35
+ you wish to see.
36
+
37
+ Attributes include: "all", "basic", "breakpoint", "lines", "mtime", "path"
38
+ and "sha1".'],
39
+ ['files', 5, 'File names and timestamps of files read in'],
40
+ ['global_variables', 2, 'Global variables'],
41
+ ['instance_variables', 2,
42
+ 'Instance variables of the current stack frame'],
43
+ ['line', 2,
44
+ 'Line number and file name of current position in source file'],
45
+ ['locals', 2, 'Local variables of the current stack frame'],
46
+ ['program', 2, 'Execution status of the program'],
47
+ ['stack', 2, 'Backtrace of the stack'],
48
+ ['thread', 6, 'List info about thread NUM', '
49
+ If no thread number is given, we list info for all threads. \'terse\' and \'verbose\'
50
+ options are possible. If terse, just give summary thread name information. See
51
+ "help info threads" for more detail about this summary information.
52
+
53
+ If \'verbose\' appended to the end of the command, then the entire
54
+ stack trace is given for each thread.'],
55
+ ['threads', 7, 'information of currently-known threads', '
56
+ This information includes whether the thread is current (+), if it is
57
+ suspended ($), or ignored (!). The thread number and the top stack
58
+ item. If \'verbose\' is given then the entire stack frame is shown.'],
59
+ ['variables', 1,
60
+ 'Local and instance variables of the current stack frame']
61
+ ].map do |name, min, short_help, long_help|
62
+ SubcmdStruct.new(name, min, short_help, long_help)
63
+ end unless defined?(Subcommands)
64
+
65
+ InfoFileSubcommands =
66
+ [
67
+ ['all', 1,
68
+ 'All file information available - breakpoints, lines, mtime, path, and sha1'],
69
+ ['basic', 2,
70
+ 'basic information - path, number of lines'],
71
+ ['breakpoints', 2, 'Show trace line numbers',
72
+ 'These are the line number where a breakpoint can be set.'],
73
+ ['lines', 1, 'Show number of lines in the file'],
74
+ ['mtime', 1, 'Show modification time of file'],
75
+ ['path', 4, 'Show full file path name for file'],
76
+ ['sha1', 1, 'Show SHA1 hash of contents of the file']
77
+ ].map do |name, min, short_help, long_help|
78
+ SubcmdStruct.new(name, min, short_help, long_help)
79
+ end unless defined?(InfoFileSubcommands)
80
+
81
+ InfoThreadSubcommands =
82
+ [
83
+ ['terse', 1, 'summary information'],
84
+ ['verbose', 1, 'summary information and stack frame info'],
85
+ ].map do |name, min, short_help, long_help|
86
+ SubcmdStruct.new(name, min, short_help, long_help)
87
+ end unless defined?(InfoThreadSubcommands)
88
+
89
+ def regexp
90
+ /^\s* i(?:nfo)? (?:\s+(.*))?$/ix
91
+ end
92
+
93
+ def execute
94
+ if !@match[1]
95
+ errmsg "\"info\" must be followed by the name of an info command:\n"
96
+ print "List of info subcommands:\n\n"
97
+ for subcmd in Subcommands do
98
+ print "info #{subcmd.name} -- #{subcmd.short_help}\n"
99
+ end
100
+ else
101
+ args = @match[1].split(/[ \t]+/)
102
+ param = args.shift
103
+ subcmd = find(Subcommands, param)
104
+ if subcmd
105
+ send("info_#{subcmd.name}", *args)
106
+ else
107
+ errmsg "Unknown info command #{param}\n"
108
+ end
109
+ end
110
+ end
111
+
112
+ def info_args(*args)
113
+ unless @state.context
114
+ print "No frame selected.\n"
115
+ return
116
+ end
117
+ locals = @state.context.frame_locals(@state.frame_pos)
118
+ args = @state.context.frame_args(@state.frame_pos)
119
+ args.each do |name|
120
+ s = "#{name} = #{locals[name].inspect}"
121
+ if s.size > self.class.settings[:width]
122
+ s[self.class.settings[:width]-3 .. -1] = "..."
123
+ end
124
+ print "#{s}\n"
125
+ end
126
+ end
127
+
128
+ def info_breakpoints(*args)
129
+ unless @state.context
130
+ print "info breakpoints not available here.\n"
131
+ return
132
+ end
133
+ unless Debugger.breakpoints.empty?
134
+ brkpts = Debugger.breakpoints.sort_by{|b| b.id}
135
+ unless args.empty?
136
+ indices = args.map{|a| a.to_i}
137
+ brkpts = brkpts.select{|b| indices.member?(b.id)}
138
+ if brkpts.empty?
139
+ errmsg "No breakpoints found among list given.\n"
140
+ return
141
+ end
142
+ end
143
+ print "Num Enb What\n"
144
+ brkpts.each do |b|
145
+ if b.expr.nil?
146
+ print "%3d %s at %s:%s\n",
147
+ b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos
148
+ else
149
+ print "%3d %s at %s:%s if %s\n",
150
+ b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos, b.expr
151
+ end
152
+ hits = b.hit_count
153
+ if hits > 0
154
+ s = (hits > 1) ? 's' : ''
155
+ print "\tbreakpoint already hit #{hits} time#{s}\n"
156
+ end
157
+ end
158
+ else
159
+ print "No breakpoints.\n"
160
+ end
161
+ end
162
+
163
+ def info_display(*args)
164
+ unless @state.context
165
+ print "info display not available here.\n"
166
+ return
167
+ end
168
+ if @state.display.find{|d| d[0]}
169
+ print "Auto-display expressions now in effect:\n"
170
+ print "Num Enb Expression\n"
171
+ n = 1
172
+ for d in @state.display
173
+ print "%3d: %s %s\n", n, (d[0] ? 'y' : 'n'), d[1] if
174
+ d[0] != nil
175
+ n += 1
176
+ end
177
+ else
178
+ print "There are no auto-display expressions now.\n"
179
+ end
180
+ end
181
+
182
+ def info_file(*args)
183
+ unless args[0]
184
+ info_files
185
+ return
186
+ end
187
+ file = args[0]
188
+ param = args[1]
189
+
190
+ param = 'basic' unless param
191
+ subcmd = find(InfoFileSubcommands, param)
192
+ unless subcmd
193
+ errmsg "Invalid parameter #{param}\n"
194
+ return
195
+ end
196
+
197
+ unless LineCache::cached?(file)
198
+ unless LineCache::cached_script?(file)
199
+ print "File #{file} is not cached\n"
200
+ return
201
+ end
202
+ LineCache::cache(file, Command.settings[:reload_source_on_change])
203
+ end
204
+
205
+ print "File %s", file
206
+ path = LineCache.path(file)
207
+ if %w(all basic path).member?(subcmd.name) and path != file
208
+ print " - %s\n", path
209
+ else
210
+ print "\n"
211
+ end
212
+
213
+ if %w(all basic lines).member?(subcmd.name)
214
+ lines = LineCache.size(file)
215
+ print "\t %d lines\n", lines if lines
216
+ end
217
+
218
+ if %w(all breakpoints).member?(subcmd.name)
219
+ breakpoints = LineCache.trace_line_numbers(file)
220
+ if breakpoints
221
+ print "\tbreakpoint line numbers:\n"
222
+ print columnize(breakpoints.to_a.sort, self.class.settings[:width])
223
+ end
224
+ end
225
+
226
+ if %w(all mtime).member?(subcmd.name)
227
+ stat = LineCache.stat(file)
228
+ print "\t%s\n", stat.mtime if stat
229
+ end
230
+ if %w(all sha1).member?(subcmd.name)
231
+ print "\t%s\n", LineCache.sha1(file)
232
+ end
233
+ end
234
+
235
+ def info_files(*args)
236
+ files = LineCache::cached_files
237
+ files += SCRIPT_LINES__.keys unless 'stat' == args[0]
238
+ files.uniq.sort.each do |file|
239
+ stat = LineCache::stat(file)
240
+ path = LineCache::path(file)
241
+ print "File %s", file
242
+ if path and path != file
243
+ print " - %s\n", path
244
+ else
245
+ print "\n"
246
+ end
247
+ print "\t%s\n", stat.mtime if stat
248
+ end
249
+ end
250
+
251
+ def info_instance_variables(*args)
252
+ unless @state.context
253
+ print "info instance_variables not available here.\n"
254
+ return
255
+ end
256
+ obj = debug_eval('self')
257
+ var_list(obj.instance_variables)
258
+ end
259
+
260
+ def info_line(*args)
261
+ unless @state.context
262
+ errmsg "info line not available here.\n"
263
+ return
264
+ end
265
+ print "Line %d of \"%s\"\n", @state.line, @state.file
266
+ end
267
+
268
+ def info_locals(*args)
269
+ unless @state.context
270
+ errmsg "info line not available here.\n"
271
+ return
272
+ end
273
+ locals = @state.context.frame_locals(@state.frame_pos)
274
+ locals.keys.sort.each do |name|
275
+ ### FIXME: make a common routine
276
+ begin
277
+ s = "#{name} = #{locals[name].inspect}"
278
+ rescue
279
+ begin
280
+ s = "#{name} = #{locals[name].to_s}"
281
+ rescue
282
+ s = "*Error in evaluation*"
283
+ end
284
+ end
285
+ if s.size > self.class.settings[:width]
286
+ s[self.class.settings[:width]-3 .. -1] = "..."
287
+ end
288
+ print "#{s}\n"
289
+ end
290
+ end
291
+
292
+ def info_program(*args)
293
+ if not @state.context
294
+ print "The program being debugged is not being run.\n"
295
+ return
296
+ elsif @state.context.dead?
297
+ print "The program crashed.\n"
298
+ if Debugger.last_exception
299
+ print("Exception: #{Debugger.last_exception.inspect}\n")
300
+ end
301
+ return
302
+ end
303
+
304
+ print "Program stopped. "
305
+ case @state.context.stop_reason
306
+ when :step
307
+ print "It stopped after stepping, next'ing or initial start.\n"
308
+ when :breakpoint
309
+ print("It stopped at a breakpoint.\n")
310
+ when :catchpoint
311
+ print("It stopped at a catchpoint.\n")
312
+ else
313
+ print "unknown reason: %s\n" % @state.context.stop_reason.to_s
314
+ end
315
+ end
316
+
317
+ def info_stack(*args)
318
+ if not @state.context
319
+ errmsg "info stack not available here.\n"
320
+ return
321
+ end
322
+ (0...@state.context.stack_size).each do |idx|
323
+ if idx == @state.frame_pos
324
+ print "--> "
325
+ else
326
+ print " "
327
+ end
328
+ print_frame(idx)
329
+ end
330
+ end
331
+
332
+ def info_thread_preamble(arg)
333
+ if not @state.context
334
+ errmsg "info threads not available here.\n"
335
+ return false, false
336
+ end
337
+ verbose = if arg
338
+ subcmd = find(InfoThreadSubcommands, arg)
339
+ unless subcmd
340
+ errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n"
341
+ return false, false
342
+ end
343
+ 'verbose' == subcmd.name
344
+ else
345
+ false
346
+ end
347
+ return true, verbose
348
+ end
349
+ private :info_thread_preamble
350
+
351
+ def info_threads(*args)
352
+ ok, verbose = info_thread_preamble(args[0])
353
+ return unless ok
354
+ threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c|
355
+ display_context(c, !verbose)
356
+ if verbose and not c.ignored?
357
+ (0...c.stack_size).each do |idx|
358
+ print "\t"
359
+ print_frame(idx, false, c)
360
+ end
361
+ end
362
+ end
363
+ end
364
+
365
+ def info_thread(*args)
366
+ unless args[0]
367
+ info_threads(args[0])
368
+ return
369
+ end
370
+ ok, verbose = info_thread_preamble(args[1])
371
+ return unless ok
372
+ c = parse_thread_num("info thread" , args[0])
373
+ return unless c
374
+ display_context(c, !verbose)
375
+ if verbose and not c.ignored?
376
+ (0...c.stack_size).each do |idx|
377
+ print "\t"
378
+ print_frame(idx, false, c)
379
+ end
380
+ end
381
+ end
382
+
383
+ def info_global_variables(*args)
384
+ unless @state.context
385
+ errmsg "info global_variables not available here.\n"
386
+ return
387
+ end
388
+ var_list(global_variables)
389
+ end
390
+
391
+ def info_variables(*args)
392
+ if not @state.context
393
+ errmsg "info variables not available here.\n"
394
+ return
395
+ end
396
+ obj = debug_eval('self')
397
+ locals = @state.context.frame_locals(@state.frame_pos)
398
+ locals[:self] = @state.context.frame_self(@state.frame_pos)
399
+ locals.keys.sort.each do |name|
400
+ next if name =~ /^__dbg_/ # skip debugger pollution
401
+ ### FIXME: make a common routine
402
+ begin
403
+ s = "#{name} = #{locals[name].inspect}"
404
+ rescue
405
+ begin
406
+ s = "#{name} = #{locals[name].to_s}"
407
+ rescue
408
+ s = "#{name} = *Error in evaluation*"
409
+ end
410
+ end
411
+ if s.size > self.class.settings[:width]
412
+ s[self.class.settings[:width]-3 .. -1] = "..."
413
+ end
414
+ s.gsub!('%', '%%') # protect against printf format strings
415
+ print "#{s}\n"
416
+ end
417
+ var_list(obj.instance_variables, obj.instance_eval{binding()})
418
+ var_class_self
419
+ end
420
+
421
+ class << self
422
+ def help_command
423
+ 'info'
424
+ end
425
+
426
+ def help(args)
427
+ if args[1]
428
+ s = args[1]
429
+ subcmd = Subcommands.find do |try_subcmd|
430
+ (s.size >= try_subcmd.min) and
431
+ (try_subcmd.name[0..s.size-1] == s)
432
+ end
433
+ if subcmd
434
+ str = subcmd.short_help + '.'
435
+ if 'file' == subcmd.name and args[2]
436
+ s = args[2]
437
+ subsubcmd = InfoFileSubcommands.find do |try_subcmd|
438
+ (s.size >= try_subcmd.min) and
439
+ (try_subcmd.name[0..s.size-1] == s)
440
+ end
441
+ if subsubcmd
442
+ str += "\n" + subsubcmd.short_help + '.'
443
+ else
444
+ str += "\nInvalid file attribute #{args[2]}."
445
+ end
446
+ else
447
+ str += "\n" + subcmd.long_help if subcmd.long_help
448
+ end
449
+ return str
450
+ else
451
+ return "Invalid 'info' subcommand '#{args[1]}'."
452
+ end
453
+ end
454
+ s = %{
455
+ Generic command for showing things about the program being debugged.
456
+ --
457
+ List of info subcommands:
458
+ --
459
+ }
460
+ for subcmd in Subcommands do
461
+ s += "info #{subcmd.name} -- #{subcmd.short_help}\n"
462
+ end
463
+ return s
464
+ end
465
+ end
466
+ end
467
+ end