trepanning 0.0.4

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 (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,103 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'base/cmd'
4
+ require_relative '../../app/disassemble'
5
+ require_relative '../../app/file'
6
+
7
+ class Trepan::Command::DisassembleCommand < Trepan::Command
8
+ include Trepan::Disassemble
9
+ include Trepanning
10
+
11
+ unless defined?(HELP)
12
+ HELP =
13
+ "disassemble [thing] [full]
14
+
15
+ With no argument, disassemble the current frame. With a method,
16
+ disassemble that method. '.' can be used to indicate the instruction
17
+ sequence for the current frame.
18
+
19
+ By default, just this instruction sequence is disassembled, not others
20
+ which may be accessed off of this one, including any catch table the
21
+ instruction sequence might have. If 'full' is given, all instruction
22
+ sequences are include.
23
+
24
+ Examples:
25
+
26
+ disassemble
27
+ disas . # Same as above
28
+ disas . full # At least the instruction sequence above but maybe more
29
+ disas require_relative # disassemble method 'require_relative'
30
+ "
31
+
32
+ ALIASES = %w(disas disassem) # Note we have disable
33
+ CATEGORY = 'data'
34
+ NAME = File.basename(__FILE__, '.rb')
35
+ NEED_STACK = true
36
+ SHORT_HELP = 'Disassemble Ruby VM instructions'
37
+ end
38
+
39
+ # FIXME: put in processor/data.rb?
40
+
41
+ def marked_disassemble(iseq, include_children)
42
+ iseqs = include_children ? iseq.child_iseqs : [iseq]
43
+ iseqs.each do |iseq|
44
+ ary = mark_disassembly(iseq.disasm_nochildren,
45
+ @proc.frame.iseq.equal?(iseq),
46
+ @proc.frame.pc_offset,
47
+ iseq.brkpts)
48
+ msg ary
49
+ end
50
+ end
51
+
52
+ # Run command.
53
+ def run(args)
54
+
55
+ obj = nil
56
+ include_children =
57
+ if args.size > 1 && args[-1] == 'full'
58
+ args.pop
59
+ true
60
+ else
61
+ false
62
+ end
63
+ if args.size == 1 || '.' == args[1]
64
+ # Form is: "disassemble" or "disassemble ."
65
+ if @proc.frame.type == 'CFUNC'
66
+ errmsg "Can't handle C functions yet."
67
+ return
68
+ elsif @proc.frame.iseq
69
+ marked_disassemble(@proc.frame.iseq, include_children)
70
+ return
71
+ end
72
+ else
73
+ if !(matches = find_iseqs(ISEQS__, args[1])).empty?
74
+ # FIXME: do something if there is more than one
75
+ iseq = matches[0]
76
+ else
77
+ iseq = @proc.object_iseq(args[1])
78
+ end
79
+ marked_disassemble(iseq, include_children) if iseq
80
+ return
81
+ end
82
+ errmsg("Sorry can't handle right now.")
83
+ end
84
+ end
85
+
86
+ if __FILE__ == $0
87
+ # Demo it.
88
+ require 'thread_frame'
89
+
90
+ require_relative '../mock'
91
+ name = File.basename(__FILE__, '.rb')
92
+ dbgr, cmd = MockDebugger::setup(name)
93
+ def small_fn(cmd, name)
94
+ cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
95
+ cmd.run [name]
96
+ end
97
+ small_fn(cmd, name)
98
+ p = Proc.new do
99
+ |x,y| x + y
100
+ end
101
+ cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
102
+ cmd.run([name, 'p'])
103
+ end
@@ -0,0 +1,81 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'base/cmd'
4
+
5
+ class Trepan::Command::DisplayCommand < Trepan::Command
6
+
7
+ unless defined?(HELP)
8
+ HELP = <<EOH
9
+ display [format] EXP
10
+
11
+ Print value of expression EXP each time the program stops. FMT may be
12
+ used before EXP and may be one of 'c' for char, 'x' for hex, 'o' for
13
+ octal, 'f' for float or 's' for string.
14
+
15
+ For now, display expressions are only evaluated when in the same
16
+ instruction sequence as the frame that was in effect when the display
17
+ expression was set. This is a departure from gdb and we may allow for
18
+ more flexibility in the future to specify whether this should be the
19
+ case or not.
20
+
21
+ With no argument, evaluate and display all currently requested
22
+ auto-display expressions. Use "undisplay" to cancel display
23
+ requests previously made.
24
+ EOH
25
+
26
+ CATEGORY = 'data'
27
+ NAME = File.basename(__FILE__, '.rb')
28
+ NEED_STACK = false
29
+ SHORT_HELP = 'Display expressions when entering debugger'
30
+ end
31
+
32
+ def run(args)
33
+
34
+ if args.size == 1
35
+ # Display anything active
36
+ @proc.run_eval_display
37
+ else
38
+ if %w(/c /x /o /f /s).member?(args[1])
39
+ if 2 == args.size
40
+ errmsg("Expecting an expression after the format")
41
+ return
42
+ end
43
+ format = args[1]
44
+ expr = args[2..-1].join(' ')
45
+ else
46
+ format = nil
47
+ expr = args[1..-1].join(' ')
48
+ end
49
+
50
+ dp = @proc.displays.add(@proc.frame, expr, format)
51
+ unless dp
52
+ errmsg('Error evaluating "%s" in the current frame' % expr)
53
+ return
54
+ end
55
+ msg(dp.to_s(@proc.frame))
56
+ @proc.cmdloop_prehooks.insert_if_new(5, *@proc.display_hook)
57
+ end
58
+ end
59
+ end
60
+
61
+ if __FILE__ == $0
62
+ # Demo it.
63
+ require 'thread_frame'
64
+ require_relative '../mock'
65
+ name = File.basename(__FILE__, '.rb')
66
+ dbgr, cmd = MockDebugger::setup(name)
67
+
68
+ def run_cmd(cmd, args)
69
+ cmd.run(args)
70
+ puts '==' * 10
71
+ end
72
+
73
+ cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
74
+
75
+ run_cmd(cmd, [name])
76
+ run_cmd(cmd, [name, '/x', '10'])
77
+ run_cmd(cmd, [name, 'd'])
78
+ run_cmd(cmd, [name])
79
+ e = 5
80
+ run_cmd(cmd, [name, 'e'])
81
+ end
@@ -0,0 +1,56 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'up'
4
+
5
+ # Debugger "down" command. Is the same as the "up" command with the
6
+ # direction (set by DIRECTION) reversed.
7
+ class Trepan::Command::DownCommand < Trepan::Command::UpCommand
8
+
9
+ # Silence already initialized constant .. warnings
10
+ old_verbose = $VERBOSE
11
+ $VERBOSE = nil
12
+ HELP =
13
+ "d(own) [count]
14
+
15
+ Move the current frame down in the stack trace (to a newer frame). 0
16
+ is the most recent frame. If no count is given, move down 1.
17
+
18
+ See also 'up' and 'frame'.
19
+ "
20
+
21
+ ALIASES = %w(d)
22
+ NAME = File.basename(__FILE__, '.rb')
23
+ SHORT_HELP = 'Move frame in the direction of the caller of the last-selected frame'
24
+ $VERBOSE = old_verbose
25
+
26
+ def initialize(proc)
27
+ super
28
+ @direction = -1 # +1 for up.
29
+ end
30
+
31
+ end
32
+
33
+ if __FILE__ == $0
34
+ # Demo it.
35
+ require 'thread_frame'
36
+ require_relative '../mock'
37
+ name = File.basename(__FILE__, '.rb')
38
+ dbgr, cmd = MockDebugger::setup(name)
39
+
40
+ def sep ; puts '=' * 40 end
41
+ cmd.run [name]
42
+ %w(-1 0 1 -2).each do |count|
43
+ puts "#{name} #{count}"
44
+ cmd.run([name, count])
45
+ sep
46
+ end
47
+ def foo(cmd, name)
48
+ cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
49
+ puts "#{name}"
50
+ cmd.run([name])
51
+ sep
52
+ puts "#{name} -1"
53
+ cmd.run([name, '-1'])
54
+ end
55
+ foo(cmd, name)
56
+ end
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'disable'
4
+
5
+ # enable breakpoint command. Is like disable but the parameter
6
+ # to @proc.en_disable_breakpoint_by_number is different (set as
7
+ # ENABLE_PARM below).
8
+ class Trepan::Command::EnableCommand < Trepan::Command::DisableCommand
9
+
10
+ # Silence already initialized constant .. warnings
11
+ old_verbose = $VERBOSE
12
+ $VERBOSE = nil
13
+ HELP =
14
+ 'enable [display] bpnumber [bpnumber ...]
15
+
16
+ Enables the breakpoints given as a space separated list of breakpoint
17
+ numbers. See also "info break" to get a list.
18
+ '
19
+
20
+ ALIASES = %w(en)
21
+ NAME = File.basename(__FILE__, '.rb')
22
+ SHORT_HELP = 'Enable some breakpoints'
23
+ $VERBOSE = old_verbose
24
+
25
+ def initialize(proc)
26
+ super
27
+ @enable_parm = true # true if enable
28
+ end
29
+
30
+ end
31
+
32
+ if __FILE__ == $0
33
+ require_relative '../mock'
34
+ name = File.basename(__FILE__, '.rb')
35
+ dbgr, cmd = MockDebugger::setup(name)
36
+ cmd.run([name])
37
+ cmd.run([name, '1'])
38
+ cmdproc = dbgr.core.processor
39
+ cmds = cmdproc.commands
40
+ break_cmd = cmds['break']
41
+ break_cmd.run(['break', cmdproc.frame.source_location[0].to_s])
42
+ cmd.run([name, '1'])
43
+ end
@@ -0,0 +1,54 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require_relative 'base/cmd'
3
+ class Trepan::Command::ExitCommand < Trepan::Command
4
+
5
+ unless defined?(HELP)
6
+ HELP =
7
+ 'exit [exitcode] - hard exit of the debugged program.
8
+
9
+ The program being debugged is exited via exit!() which does not run
10
+ the Kernel at_exit finalizers. If a return code is given, that is the
11
+ return code passed to exit() - presumably the return code that will be
12
+ passed back to the OS. If no exit code is given, 0 is used.
13
+
14
+ See also the commands "quit" and "kill".'
15
+
16
+ CATEGORY = 'support'
17
+ MAX_ARGS = 2 # Need at most this many
18
+ NAME = File.basename(__FILE__, '.rb')
19
+ SHORT_HELP = 'Exit program via "exit!"'
20
+ end
21
+
22
+ # FIXME: Combine 'quit' and 'exit'. The only difference is
23
+ # whether exit! or exit is used.
24
+
25
+ # This method runs the command
26
+ def run(args) # :nodoc
27
+ unconditional =
28
+ if args.size > 1 && args[1] == 'unconditionally'
29
+ args.shift
30
+ true
31
+ elsif args[0][-1..-1] == '!'
32
+ true
33
+ else
34
+ false
35
+ end
36
+ unless unconditional || confirm('Really quit?', false)
37
+ msg('Quit not confirmed.')
38
+ return
39
+ end
40
+ exitrc = (args.size > 1) ? exitrc = Integer(args[1]) rescue 0 : 0
41
+ # No graceful way to stop threads...
42
+ # A little harsh, but for now let's go with this.
43
+ exit! exitrc
44
+ end
45
+ end
46
+
47
+ if __FILE__ == $0
48
+ require_relative '../mock'
49
+ name = File.basename(__FILE__, '.rb')
50
+ dbgr, cmd = MockDebugger::setup(name)
51
+ name = File.basename(__FILE__, '.rb')
52
+ fork { cmd.run([name]) }
53
+ cmd.run([name, '10'])
54
+ end
@@ -0,0 +1,81 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative 'base/cmd'
4
+
5
+ class Trepan::Command::FinishCommand < Trepan::Command
6
+
7
+ unless defined?(HELP)
8
+ HELP =
9
+ "finish [levels]
10
+
11
+ Continue execution until leaving the current function.
12
+ Sometimes this is called 'step out'.
13
+
14
+ When `levels' is specified, that many frame levels need to be
15
+ popped. The default is 1. Note that 'yield' and exceptions raised my
16
+ reduce the number of stack frames. Also, if a thread is switched, we
17
+ stop ignoring levels.
18
+
19
+ 'next>' is similar in that it stops at a return, but it doesn't
20
+ guarentee the stack level is the same as or less than the current
21
+ one.
22
+
23
+ See the break command if you want to stop at a particular point in a
24
+ program. In general, 'finish', 'step' and 'next' may slow a program down
25
+ while 'break' will have less overhead.
26
+ "
27
+ ALIASES = %w(fin)
28
+ CATEGORY = 'running'
29
+ # execution_set = ['Running']
30
+ MAX_ARGS = 1 # Need at most this many.
31
+ NAME = File.basename(__FILE__, '.rb')
32
+ NEED_STACK = true
33
+ SHORT_HELP = 'Step program without entering called functions'
34
+ end
35
+
36
+ # This method runs the command
37
+ def run(args) # :nodoc
38
+ opts = {}
39
+ if args.size == 1
40
+ # Form is: "finish" which means "finish 1"
41
+ level_count = 0
42
+ else
43
+ count_str = args[1]
44
+ opts = {
45
+ :msg_on_error =>
46
+ "The 'next' command argument must eval to an integer. Got: %s" %
47
+ count_str,
48
+ :min_value => 1
49
+ }
50
+ count = @proc.get_an_int(count_str, opts)
51
+ return unless count
52
+ # step 1 is core.level_count = 0 or "stop next event"
53
+ level_count = count - 1
54
+ end
55
+ if 0 == level_count and %w(return c-return).member?(@proc.event)
56
+ errmsg "You are already at the requested return event."
57
+ else
58
+ @proc.finish(level_count, opts)
59
+ end
60
+ end
61
+ end
62
+
63
+ if __FILE__ == $0
64
+ require_relative '../mock'
65
+ name = File.basename(__FILE__, '.rb')
66
+ dbgr, cmd = MockDebugger::setup(name)
67
+ [%w(finish 1), %w(fin 2-1), %w(n foo)].each do |c|
68
+ cmd.proc.next_level = 0
69
+ cmd.proc.leave_cmd_loop = false
70
+ result = cmd.run(c)
71
+ puts 'Run result: %s' % result
72
+ puts 'level_count %d, leave_cmd_loop: %s' % [cmd.proc.next_level,
73
+ cmd.proc.leave_cmd_loop]
74
+ end
75
+ [%w(fin), %w(finish)].each do |c|
76
+ cmd.proc.next_level = 0
77
+ cmd.proc.leave_cmd_loop = false
78
+ result = cmd.run(c)
79
+ puts cmd.proc.different_pos
80
+ end
81
+ end
@@ -0,0 +1,117 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require_relative 'base/cmd'
3
+ require_relative '../../app/frame'
4
+
5
+ class Trepan::Command::FrameCommand < Trepan::Command
6
+
7
+ include Trepan::Frame
8
+
9
+ unless defined?(HELP)
10
+ HELP =
11
+ "frame [thread-Name] [frame-number]
12
+
13
+ Change the current frame to frame `frame-number' if specified, or the
14
+ most-recent frame, 0, if no frame number specified.
15
+
16
+ If a thread name or thread number is given, change the current frame
17
+ to a frame in that thread. Dot (.) can be used to indicate the name of
18
+ the current frame the debugger is stopped in.
19
+
20
+ A negative number indicates the position from the other or
21
+ least-recently-entered end. So 'frame -1' moves to the oldest frame.
22
+ Any variable or expression that evaluates to a number can be used as a
23
+ position, however due to parsing limitations, the position expression
24
+ has to be seen as a single blank-delimited parameter. That is, the
25
+ expression '(5*3)-1' is okay while '( (5 * 3) - 1 )' isn't.
26
+
27
+ Examples:
28
+ frame # Set current frame at the current stopping point
29
+ frame 0 # Same as above
30
+ frame 5-5 # Same as above. Note: no spaces allowed in expression 5-5
31
+ frame . # Same as above. 'current thread' is explicit.
32
+ frame . 0 # Same as above.
33
+ frame 1 # Move to frame 1. Same as: frame 0; up
34
+ frame -1 # The least-recent frame
35
+ frame MainThread 0 # Switch to frame 0 of thread MainThread
36
+ frame MainThread # Same as above
37
+ frame -2434343 0 # Use a thread number instead of name
38
+
39
+ See also 'up', 'down' 'where' and 'info thread'.
40
+ "
41
+
42
+ CATEGORY = 'stack'
43
+ MAX_ARGS = 2 # Need at most this many
44
+ NAME = File.basename(__FILE__, '.rb')
45
+ NEED_STACK = true
46
+ SHORT_HELP = 'Select and print a stack frame'
47
+ end
48
+
49
+ # The simple case: thread frame switching has been done or is
50
+ # not needed and we have an explicit position number as a string
51
+ def one_arg_run(position_str)
52
+ stack_size = @proc.top_frame.stack_size - @proc.hide_level
53
+ opts={
54
+ :msg_on_error =>
55
+ "The '#{NAME}' command requires a frame number. Got: #{position_str}",
56
+ :min_value => -stack_size,
57
+ :max_value => stack_size-1
58
+ }
59
+ frame_num = @proc.get_an_int(position_str, opts)
60
+ return false unless frame_num
61
+
62
+ # FIXME: move into @proc and test based on NEED_STACK.
63
+ if not @proc.top_frame
64
+ errmsg('No frames recorded.')
65
+ return false
66
+ end
67
+
68
+ @proc.adjust_frame(frame_num, true)
69
+ return true
70
+ end
71
+
72
+ # Run a frame command. This routine is a little complex
73
+ # because we allow a number parameter variations.
74
+ def run(args)
75
+ if args.size == 1
76
+ # Form is: "frame" which means "frame 0"
77
+ position_str = '0'
78
+ elsif args.size == 2
79
+ # Form is: "frame position"
80
+ position_str = args[1]
81
+ elsif args.size == 3
82
+ # Form is: frame <position> <thread>
83
+ name_or_id = args[1]
84
+ thread_str = args[2]
85
+ th = @proc.get_thread_from_string(thread_str)
86
+ if th
87
+ @proc.frame_setup(th.threadframe)
88
+ return
89
+ else
90
+ # FIXME: Give suitable error message was given
91
+ end
92
+ else
93
+ # Form should be: "frame thread" which means
94
+ # "frame thread 0"
95
+ position_str = '0'
96
+ ## FIXME:
97
+ ## @proc.find_and_set_debugged_frame(frame, thread_id)
98
+ end
99
+ one_arg_run(position_str)
100
+ end
101
+ end
102
+
103
+ if __FILE__ == $0
104
+ # Demo it.
105
+ require 'thread_frame'
106
+ require_relative '../mock'
107
+ name = File.basename(__FILE__, '.rb')
108
+ dbgr, cmd = MockDebugger::setup(name)
109
+
110
+ def sep ; puts '=' * 40 end
111
+ %w(0 1 -2).each {|count| cmd.run([name, count]); sep }
112
+ def foo(cmd, name)
113
+ cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
114
+ %w(0 -1).each {|count| cmd.run([name, count]); sep }
115
+ end
116
+ foo(cmd, name)
117
+ end
@@ -0,0 +1,146 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require_relative 'base/cmd'
3
+ class Trepan::Command::HelpCommand < Trepan::Command
4
+
5
+ unless defined?(HELP)
6
+ HELP =
7
+ "help [command [subcommand]|expression]
8
+
9
+ Without argument, print the list of available debugger commands.
10
+
11
+ When an argument is given, it is first checked to see if it is command
12
+ name. 'help where' gives help on the 'where' debugger command.
13
+
14
+ If the environment variable $PAGER is defined, the file is
15
+ piped through that command. You'll notice this only for long help
16
+ output.
17
+
18
+ Some commands like 'info', 'set', and 'show' can accept an
19
+ additional subcommand to give help just about that particular
20
+ subcommand. For example 'help info line' give help about the
21
+ info line command.
22
+
23
+ See also 'examine' and 'whatis'.
24
+ "
25
+
26
+
27
+ ALIASES = %w(?)
28
+ CATEGORIES = {
29
+ 'breakpoints' => 'Making the program stop at certain points',
30
+ 'data' => 'Examining data',
31
+ 'files' => 'Specifying and examining files',
32
+ 'running' => 'Running the program',
33
+ 'status' => 'Status inquiries',
34
+ 'support' => 'Support facilities',
35
+ 'stack' => 'Examining the call stack'
36
+ }
37
+ CATEGORY = 'support'
38
+ NAME = File.basename(__FILE__, '.rb')
39
+ NEED_STACK = false
40
+ SHORT_HELP = 'Print commands or give help for command(s)'
41
+ end
42
+
43
+ # List the command categories and a short description of each.
44
+ def list_categories
45
+ msg("Classes of commands:")
46
+ CATEGORIES.keys.sort.each do |cat|
47
+ msg("%-13s -- %s" % [cat, CATEGORIES[cat]])
48
+ end
49
+ final_msg = '
50
+ Type "help" followed by a class name for a list of commands in that class.
51
+ Type "help *" for the list of all commands.
52
+ Type "help REGEXP" for the list of commands matching /^#{REGEXP}/
53
+ Type "help CLASS *" for the list of all commands in class CLASS.
54
+ Type "help" followed by command name for full documentation.
55
+ '
56
+ msg(final_msg)
57
+ end
58
+
59
+ # This method runs the command
60
+ def run(args) # :nodoc
61
+ if args.size > 1
62
+ cmd_name = args[1]
63
+ if cmd_name == '*'
64
+ msg("All command names:")
65
+ msg columnize_commands(@proc.commands.keys.sort)
66
+ elsif CATEGORIES.member?(cmd_name)
67
+ show_category(args[1], args[2..-1])
68
+ elsif @proc.commands.member?(cmd_name) or @proc.aliases.member?(cmd_name)
69
+ real_name =
70
+ if @proc.commands.member?(cmd_name)
71
+ cmd_name
72
+ else
73
+ @proc.aliases[cmd_name]
74
+ end
75
+ cmd_obj = @proc.commands[real_name]
76
+ help_text =
77
+ cmd_obj.respond_to?(:help) ? cmd_obj.help(args) :
78
+ cmd_obj.class.const_get(:HELP)
79
+ if help_text
80
+ msg(help_text)
81
+ if cmd_obj.class.constants.member?(:ALIASES) and
82
+ args.size == 2
83
+ msg "Aliases: #{cmd_obj.class.const_get(:ALIASES).join(', ')}"
84
+ end
85
+ end
86
+ else
87
+ matches = @proc.commands.keys.grep(/^#{cmd_name}/).sort rescue []
88
+ if matches.empty?
89
+ errmsg("No commands found matching /^#{cmd_name}/. Try \"help\".")
90
+ else
91
+ msg("Command names matching /^#{cmd_name}/:")
92
+ msg columnize_commands(matches.sort)
93
+ end
94
+ end
95
+ else
96
+ list_categories
97
+ end
98
+ return false # Don't break out of cmd loop
99
+ end
100
+
101
+ # Show short help for all commands in `category'.
102
+ def show_category(category, args)
103
+
104
+ if args.size == 1 && args[0] == '*'
105
+ msg("Commands in class %s:" % category)
106
+
107
+ cmds = @proc.commands.keys.select do |cmd_name|
108
+ category == @proc.commands[cmd_name].category
109
+ end.sort
110
+
111
+ width = settings[:maxwidth]
112
+ return columnize_commands(cmds)
113
+ end
114
+
115
+ msg("%s." % CATEGORIES[category])
116
+ msg("List of commands:\n")
117
+ @proc.commands.keys.sort.each do |name|
118
+ next if category != @proc.commands[name].category
119
+ msg("%-13s -- %s" % [name, @proc.commands[name].short_help])
120
+ end
121
+ end
122
+ end
123
+
124
+ if __FILE__ == $0
125
+ # Demo it.
126
+ require_relative '../mock'
127
+ name = File.basename(__FILE__, '.rb')
128
+ dbgr, cmd = MockDebugger::setup(name)
129
+
130
+ cmd.run %w(help help)
131
+ puts '=' * 40
132
+ cmd.run %w(help *)
133
+ puts '=' * 40
134
+ cmd.run %w(help fdafsasfda)
135
+ puts '=' * 40
136
+ cmd.run %w(help)
137
+ puts '=' * 40
138
+ cmd.run %w(help support)
139
+ puts '=' * 40
140
+ cmd.run %w(help support *)
141
+
142
+ puts '=' * 40
143
+ cmd.run %w(help s.*)
144
+ puts '=' * 40
145
+ cmd.run %w(help s<>)
146
+ end