trepanning 0.1.0 → 0.1.1

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 (181) hide show
  1. data/.gitignore +4 -0
  2. data/ChangeLog +1279 -235
  3. data/Makefile +13 -0
  4. data/NEWS +30 -0
  5. data/Rakefile +50 -14
  6. data/app/.gitignore +1 -0
  7. data/app/breakpoint.rb +7 -2
  8. data/app/brkptmgr.rb +12 -0
  9. data/app/cmd_parse.citrus +167 -0
  10. data/app/cmd_parse.kpeg +221 -0
  11. data/app/cmd_parse.rb +201 -0
  12. data/app/cmd_parser.rb +1914 -0
  13. data/app/complete.rb +79 -0
  14. data/app/condition.rb +1 -1
  15. data/app/core.rb +7 -11
  16. data/app/default.rb +1 -1
  17. data/app/disassemble.rb +3 -2
  18. data/app/file.rb +12 -36
  19. data/app/frame.rb +3 -2
  20. data/app/irb.rb +9 -5
  21. data/app/iseq.rb +46 -0
  22. data/app/options.rb +6 -30
  23. data/app/run.rb +5 -2
  24. data/app/util.rb +1 -2
  25. data/app/yarv.rb +11 -1
  26. data/bin/.gitignore +1 -0
  27. data/bin/trepan +6 -6
  28. data/data/.gitignore +1 -0
  29. data/interface/.gitignore +1 -0
  30. data/interface/base_intf.rb +9 -5
  31. data/interface/comcodes.rb +10 -8
  32. data/interface/user.rb +76 -17
  33. data/io/.gitignore +1 -0
  34. data/io/input.rb +39 -15
  35. data/io/tcpclient.rb +7 -1
  36. data/io/tcpfns.rb +5 -3
  37. data/io/tcpserver.rb +13 -10
  38. data/lib/.gitignore +1 -0
  39. data/lib/trepanning.rb +50 -13
  40. data/processor/.gitignore +1 -0
  41. data/processor/Makefile +7 -0
  42. data/processor/breakpoint.rb +7 -2
  43. data/processor/command/.gitignore +1 -0
  44. data/processor/command/Makefile +7 -0
  45. data/processor/command/alias.rb +2 -2
  46. data/processor/command/backtrace.rb +4 -0
  47. data/processor/command/base/cmd.rb +45 -2
  48. data/processor/command/base/subcmd.rb +4 -2
  49. data/processor/command/base/submgr.rb +23 -19
  50. data/processor/command/base/subsubcmd.rb +23 -1
  51. data/processor/command/base/subsubmgr.rb +13 -0
  52. data/processor/command/break.rb +34 -29
  53. data/processor/command/complete.rb +37 -0
  54. data/processor/command/condition.rb +2 -0
  55. data/processor/command/continue.rb +15 -18
  56. data/processor/command/disassemble.rb +5 -0
  57. data/processor/command/down.rb +1 -1
  58. data/processor/command/eval.rb +70 -0
  59. data/processor/command/exit.rb +4 -1
  60. data/processor/command/finish.rb +6 -4
  61. data/processor/command/frame.rb +6 -3
  62. data/processor/command/help.rb +97 -54
  63. data/processor/command/help/.gitignore +1 -0
  64. data/processor/command/help/README +10 -0
  65. data/processor/command/help/command.txt +48 -0
  66. data/processor/command/help/filename.txt +40 -0
  67. data/processor/command/help/location.txt +37 -0
  68. data/processor/command/info_subcmd/.gitignore +1 -0
  69. data/processor/command/info_subcmd/breakpoints.rb +9 -9
  70. data/processor/command/info_subcmd/{file.rb → files.rb} +92 -27
  71. data/processor/command/info_subcmd/frame.rb +41 -15
  72. data/processor/command/info_subcmd/iseq.rb +39 -17
  73. data/processor/command/info_subcmd/program.rb +2 -8
  74. data/processor/command/info_subcmd/registers.rb +12 -10
  75. data/processor/command/info_subcmd/registers_subcmd/.gitignore +1 -0
  76. data/processor/command/info_subcmd/ruby.rb +60 -0
  77. data/processor/command/irb.rb +26 -3
  78. data/processor/command/kill.rb +21 -10
  79. data/processor/command/list.rb +1 -1
  80. data/processor/command/macro.rb +37 -23
  81. data/processor/command/pr.rb +1 -1
  82. data/processor/command/reload.rb +4 -0
  83. data/processor/command/reload_subcmd/.gitignore +1 -0
  84. data/processor/command/restart.rb +9 -9
  85. data/processor/command/save.rb +29 -36
  86. data/processor/command/set_subcmd/.gitignore +1 -0
  87. data/processor/command/set_subcmd/auto_subcmd/.gitignore +1 -0
  88. data/processor/command/set_subcmd/confirm.rb +23 -0
  89. data/processor/command/set_subcmd/debug_subcmd/.gitignore +1 -0
  90. data/processor/command/set_subcmd/different.rb +2 -0
  91. data/processor/command/set_subcmd/events.rb +2 -0
  92. data/processor/command/set_subcmd/max.rb +9 -12
  93. data/processor/command/set_subcmd/max_subcmd/.gitignore +1 -0
  94. data/processor/command/set_subcmd/substitute_subcmd/.gitignore +1 -0
  95. data/processor/command/set_subcmd/trace.rb +7 -13
  96. data/processor/command/set_subcmd/trace_subcmd/.gitignore +1 -0
  97. data/processor/command/set_subcmd/trace_subcmd/buffer.rb +12 -27
  98. data/processor/command/set_subcmd/trace_subcmd/print.rb +10 -8
  99. data/processor/command/set_subcmd/trace_subcmd/var.rb +6 -10
  100. data/processor/command/show.rb +12 -1
  101. data/processor/command/show_subcmd/.gitignore +1 -0
  102. data/processor/command/show_subcmd/alias.rb +11 -15
  103. data/processor/command/show_subcmd/auto_subcmd/.gitignore +1 -0
  104. data/processor/command/show_subcmd/basename.rb +1 -9
  105. data/processor/command/show_subcmd/confirm.rb +25 -0
  106. data/processor/command/show_subcmd/debug_subcmd/.gitignore +1 -0
  107. data/processor/command/show_subcmd/macro.rb +32 -14
  108. data/processor/command/show_subcmd/max_subcmd/.gitignore +1 -0
  109. data/processor/command/show_subcmd/trace_subcmd/.gitignore +1 -0
  110. data/processor/command/show_subcmd/trace_subcmd/buffer.rb +11 -31
  111. data/processor/command/show_subcmd/trace_subcmd/print.rb +4 -20
  112. data/processor/command/source.rb +7 -1
  113. data/processor/command/up.rb +7 -4
  114. data/processor/default.rb +3 -1
  115. data/processor/eval.rb +13 -0
  116. data/processor/eventbuf.rb +3 -2
  117. data/processor/frame.rb +19 -0
  118. data/processor/help.rb +20 -0
  119. data/processor/load_cmds.rb +143 -24
  120. data/processor/location.rb +61 -10
  121. data/processor/main.rb +30 -11
  122. data/processor/mock.rb +5 -3
  123. data/processor/msg.rb +17 -0
  124. data/processor/running.rb +1 -1
  125. data/processor/subcmd.rb +3 -2
  126. data/processor/validate.rb +173 -185
  127. data/sample/.gitignore +1 -0
  128. data/sample/list-terminal-colors.rb +139 -0
  129. data/sample/rocky-dot-trepanrc +14 -0
  130. data/sample/rocky-trepan-colors.rb +47 -0
  131. data/test/Makefile +7 -0
  132. data/test/data/.gitignore +1 -0
  133. data/test/data/debugger-stop.cmd +3 -0
  134. data/test/data/debugger-stop.right +5 -0
  135. data/test/data/fname-with-blank.right +0 -3
  136. data/test/data/quit.right +0 -1
  137. data/test/data/quit2.cmd +6 -0
  138. data/test/data/quit2.right +3 -0
  139. data/test/data/testing.cmd +1 -0
  140. data/test/example/.gitignore +1 -0
  141. data/test/example/debugger-stop.rb +14 -0
  142. data/test/functional/.gitignore +2 -0
  143. data/test/functional/fn_helper.rb +7 -9
  144. data/test/functional/test-break-long.rb +7 -7
  145. data/test/functional/test-break.rb +7 -7
  146. data/test/functional/test-condition.rb +4 -4
  147. data/test/functional/test-delete.rb +6 -5
  148. data/test/functional/test-eval.rb +115 -0
  149. data/test/functional/test-raise.rb +1 -1
  150. data/test/functional/test-return.rb +1 -1
  151. data/test/integration/.gitignore +2 -0
  152. data/test/integration/helper.rb +6 -3
  153. data/test/integration/test-debugger-stop.rb +22 -0
  154. data/test/integration/test-quit.rb +8 -0
  155. data/test/unit/.gitignore +1 -0
  156. data/test/unit/Makefile +7 -0
  157. data/test/unit/test-app-brkpt.rb +0 -1
  158. data/test/unit/test-app-cmd_parse.rb +107 -0
  159. data/test/unit/test-app-cmd_parser.rb +22 -0
  160. data/test/unit/test-app-complete.rb +38 -0
  161. data/test/unit/test-app-condition.rb +20 -0
  162. data/test/unit/test-app-iseq.rb +31 -0
  163. data/test/unit/test-app-options.rb +9 -1
  164. data/test/unit/test-app-util.rb +0 -1
  165. data/test/unit/test-base-cmd.rb +46 -0
  166. data/test/unit/test-base-subcmd.rb +11 -2
  167. data/test/unit/test-base-submgr.rb +23 -0
  168. data/test/unit/test-base-subsubcmd.rb +20 -0
  169. data/test/unit/test-cmd-break.rb +22 -23
  170. data/test/unit/test-cmd-help.rb +4 -0
  171. data/test/unit/test-completion.rb +43 -0
  172. data/test/unit/test-io-tcpclient.rb +3 -2
  173. data/test/unit/test-proc-load_cmds.rb +10 -1
  174. data/test/unit/test-proc-location.rb +39 -0
  175. data/test/unit/test-proc-main.rb +1 -1
  176. data/test/unit/test-proc-validate.rb +47 -31
  177. data/trepanning.gemspec +45 -0
  178. metadata +247 -179
  179. data/app/core.rb-consider +0 -198
  180. data/test/functional/tmp/b3.rb +0 -5
  181. data/test/functional/tmp/immediate-bug1.rb +0 -9
@@ -14,13 +14,5 @@ end
14
14
  if __FILE__ == $0
15
15
  # Demo it.
16
16
  require_relative '../../mock'
17
-
18
- # FIXME: DRY the below code
19
- dbgr, cmd = MockDebugger::setup('show')
20
- subcommand = Trepan::Subcommand::ShowBasename.new(cmd)
21
- testcmdMgr = Trepan::Subcmd.new(subcommand)
22
-
23
- subcommand.run_show_bool
24
- name = File.basename(__FILE__, '.rb')
25
- subcommand.summary_help(name)
17
+ cmd = MockDebugger::sub_setup(Trepan::Subcommand::ShowBasename)
26
18
  end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require_relative '../base/subcmd'
4
+
5
+ class Trepan::Subcommand::ShowConfirm < Trepan::ShowBoolSubcommand
6
+ unless defined?(HELP)
7
+ Trepanning::Subcommand.set_name_prefix(__FILE__, self)
8
+ HELP = "Show confirm potentially dangerous operations setting"
9
+ MIN_ABBREV = 'co'.size
10
+ end
11
+ end
12
+
13
+ if __FILE__ == $0
14
+ # Demo it.
15
+ require_relative '../../mock'
16
+
17
+ # FIXME: DRY the below code
18
+ dbgr, cmd = MockDebugger::setup('show')
19
+ subcommand = Trepan::Subcommand::ShowConfirm.new(cmd)
20
+ testcmdMgr = Trepan::Subcmd.new(subcommand)
21
+
22
+ subcommand.run_show_bool
23
+ name = File.confirm(__FILE__, '.rb')
24
+ subcommand.summary_help(name)
25
+ end
@@ -1,21 +1,46 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
3
  require_relative '../base/subcmd'
4
+ require_relative '../../../app/complete'
4
5
 
5
6
  class Trepan::Subcommand::ShowMacro < Trepan::Subcommand
6
7
  unless defined?(HELP)
7
8
  Trepanning::Subcommand.set_name_prefix(__FILE__, self)
8
- HELP = "Show defined macros"
9
+ HELP = <<-HELP
10
+ #{CMD}
11
+ #{CMD} *
12
+ #{CMD} MACRO1 [MACRO2 ..]
13
+
14
+ In the first form a list of the existing macro names are shown
15
+ in column format.
16
+
17
+ In the second form, all macro names and their definitions are show.
18
+
19
+ In the last form the only definitions of the given macro names is shown.
20
+ HELP
21
+ SHORT_HELP = "Show defined macros"
9
22
  MIN_ABBREV = 'ma'.size
10
23
  end
11
24
 
25
+ def complete(prefix)
26
+ Trepan::Complete.complete_token(@proc.macros.keys + %w(*), prefix)
27
+ end
28
+
12
29
  def run(args)
13
30
  if args.size > 2
14
- args[2..-1].each do |macro_name|
31
+ macro_names =
32
+ if args.size == 3 && '*' == args[2]
33
+ @proc.macros.keys
34
+ else
35
+ args[2..-1]
36
+ end
37
+ macro_names.each do |macro_name|
15
38
  if @proc.macros.member?(macro_name)
16
- msg "%s: %s" % [macro_name, @proc.macros[macro_name]]
39
+ section "#{macro_name}:"
40
+ string = @proc.macros[macro_name][1]
41
+ msg " #{@proc.ruby_format(string)}", {:unlimited => true}
17
42
  else
18
- msg "%s is not a defined macro" % macro_name
43
+ errmsg "%s is not a defined macro" % macro_name
19
44
  end
20
45
  end
21
46
  elsif @proc.macros.empty?
@@ -29,15 +54,8 @@ end
29
54
 
30
55
  if __FILE__ == $0
31
56
  # Demo it.
57
+ $0 = __FILE__ + 'notagain' # So we don't run this agin
32
58
  require_relative '../../mock'
33
-
34
- # FIXME: DRY the below code
35
- dbgr, cmd = MockDebugger::setup('show')
36
- subcommand = Trepan::Subcommand::ShowMacro.new(cmd)
37
- testcmdMgr = Trepan::Subcmd.new(subcommand)
38
-
39
- name = File.basename(__FILE__, '.rb')
40
- subcommand.summary_help(name)
41
- subcommand.run(%W(show #{name}))
42
- subcommand.run(%W(show #{name} u foo))
59
+ cmd = MockDebugger::sub_setup(Trepan::Subcommand::ShowMacro)
60
+ cmd.run(cmd.prefix + %w(u foo))
43
61
  end
@@ -1,11 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
3
  require_relative '../../base/subsubcmd'
4
4
 
5
5
  class Trepan::SubSubcommand::ShowTraceBuffer < Trepan::ShowBoolSubSubcommand
6
+ Trepanning::SubSubcommand.set_name_prefix(__FILE__, self)
6
7
  unless defined?(HELP)
7
- HELP =
8
- "show trace buffer [NUM]
8
+ HELP = <<-EOH
9
+ #{CMD} [NUM]
9
10
 
10
11
  Show the events recorded in the event buffer. If NUM is a negative
11
12
  number, events run starting from that many debugger stops back. If NUM
@@ -13,15 +14,13 @@ is a positive number, we print starting from that (adjusted) position
13
14
  in the event buffer with Since the event buffer may be a ring, its
14
15
  zero being the first position. (Since the event buffer may be a ring
15
16
  the earliest position recorded may move around.)
16
- "
17
+ EOH
17
18
  MIN_ABBREV = 'b'.size
18
- NAME = File.basename(__FILE__, '.rb')
19
- PREFIX = %w(show trace buffer)
20
19
  SHORT_HELP = "Show tracing buffer"
21
20
  end
22
21
 
23
22
  def parse_show_buffer_args(args)
24
- marksize = @proc.eventbuf.marks.size
23
+ marksize = @proc.eventbuf.size
25
24
  opts = {
26
25
  :max_value => @proc.eventbuf.size,
27
26
  :min_value => - marksize,
@@ -30,12 +29,8 @@ the earliest position recorded may move around.)
30
29
  }
31
30
  num = @proc.get_an_int(args[0], opts)
32
31
  return nil, nil unless num
33
- first =
34
- if num < 0
35
- @proc.eventbuf.marks[marksize+num]
36
- else
37
- @proc.eventbuf.zero_pos + num
38
- end
32
+ num = marksize + num if num < 0
33
+ first = @proc.eventbuf.zero_pos + num
39
34
  return first, nil
40
35
  end
41
36
 
@@ -63,22 +58,7 @@ if __FILE__ == $0
63
58
  # Demo it.
64
59
  require_relative '../../../mock'
65
60
  require_relative '../../../subcmd'
66
- name = File.basename(__FILE__, '.rb')
67
-
68
- # FIXME: DRY the below code
69
- dbgr, show_cmd = MockDebugger::setup('show')
70
- testcmdMgr = Trepan::Subcmd.new(show_cmd)
71
- trace_cmd = Trepan::SubSubcommand::ShowTrace.new(dbgr.core.processor,
72
- show_cmd)
73
-
74
- # FIXME: remove the 'join' below
75
- cmd_name = Trepan::SubSubcommand::ShowTraceBuffer::PREFIX.join('')
76
- tb_cmd = Trepan::SubSubcommand::ShowTraceBuffer.new(show_cmd.proc,
77
- trace_cmd,
78
- cmd_name)
79
- # require_relative '../../../../lib/trepanning'
80
- # dbgr = Trepan.new
81
- # dbgr.debugger
82
- tb_cmd.run([])
83
-
61
+ require_relative '../trace'
62
+ cmd = MockDebugger::subsub_setup(Trepan::SubSubcommand::ShowTrace,
63
+ Trepan::SubSubcommand::ShowTraceBuffer)
84
64
  end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
3
  require_relative '../../base/subsubcmd'
4
4
 
5
5
  class Trepan::SubSubcommand::ShowTracePrint < Trepan::ShowBoolSubSubcommand
@@ -16,23 +16,7 @@ end
16
16
  if __FILE__ == $0
17
17
  # Demo it.
18
18
  require_relative '../../../mock'
19
- require_relative '../../../subcmd'
20
- name = File.basename(__FILE__, '.rb')
21
-
22
- # FIXME: DRY the below code
23
- dbgr, show_cmd = MockDebugger::setup('show')
24
- testcmdMgr = Trepan::Subcmd.new(show_cmd)
25
- trace_cmd = Trepan::SubSubcommand::ShowTrace.new(dbgr.core.processor,
26
- show_cmd)
27
-
28
- # FIXME: remove the 'join' below
29
- cmd_name = Trepan::SubSubcommand::ShowTracePrint::PREFIX.join('')
30
- tb_cmd = Trepan::SubSubcommand::ShowTracePrint.new(show_cmd.proc,
31
- trace_cmd,
32
- cmd_name)
33
- # require_relative '../../../../lib/trepanning'
34
- # dbgr = Trepan.new
35
- # dbgr.debugger
36
- tb_cmd.run([])
37
-
19
+ require_relative '../trace'
20
+ cmd = MockDebugger::subsub_setup(Trepan::SubSubcommand::ShowTrace,
21
+ Trepan::SubSubcommand::ShowTracePrint)
38
22
  end
@@ -9,7 +9,6 @@ require_relative '../../io/null_output'
9
9
  require_relative '../../app/default'
10
10
 
11
11
  class Trepan::Command::SourceCommand < Trepan::Command
12
- include Trepanning
13
12
  unless defined?(HELP)
14
13
  NAME = File.basename(__FILE__, '.rb')
15
14
  HELP = <<-HELP
@@ -49,6 +48,13 @@ unless option -c or --continue is given.
49
48
 
50
49
  end
51
50
 
51
+ def complete(prefix)
52
+ # opts = %w(-c --continue --no-continue -N --no -y --yes
53
+ # --verbose --no-verbose)
54
+ # return Trepan::Complete.complete_token(opts, prefix) if prefix.empty?
55
+ Readline::FILENAME_COMPLETION_PROC.call(prefix) || []
56
+ end
57
+
52
58
  def parse_options(options, args) # :nodoc
53
59
  seen_yes_no = false
54
60
  parser = OptionParser.new do |opts|
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
1
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
2
  require_relative 'base/cmd'
3
3
 
4
4
  # up command. Like 'down' butthe direction (set by DIRECTION) is different.
@@ -29,6 +29,10 @@ See also 'down' and 'frame'.
29
29
  require_relative '../../app/frame'
30
30
  include Trepan::Frame
31
31
 
32
+ def complete(prefix)
33
+ @proc.frame_complete(prefix, @direction)
34
+ end
35
+
32
36
  def initialize(proc)
33
37
  super
34
38
  @direction = +1 # -1 for down.
@@ -47,14 +51,13 @@ See also 'down' and 'frame'.
47
51
  # Form is: "down" which means "down 1"
48
52
  count = 1
49
53
  else
50
- stack_size = @proc.top_frame.stack_size - @proc.hide_level
54
+ low, high = @proc.frame_low_high(@direction)
51
55
  count_str = args[1]
52
56
  name_or_id = args[1]
53
57
  opts = {
54
58
  :msg_on_error =>
55
59
  "The '#{NAME}' command argument requires a frame number. Got: %s" % count_str,
56
- :min_value => -stack_size,
57
- :max_value => stack_size-1
60
+ :min_value => low, :max_value => high
58
61
  }
59
62
  count = @proc.get_an_int(count_str, opts)
60
63
  return false unless count
data/processor/default.rb CHANGED
@@ -9,6 +9,7 @@ class Trepan
9
9
  :autolist => false, # Run 'list'
10
10
 
11
11
  :basename => false, # Show basename of filenames only
12
+ :confirm => true, # Confirm potentially dangerous operations?
12
13
  :different => 'nostack', # stop *only* when different position?
13
14
 
14
15
  :debugdbgr => false, # Debugging the debugger
@@ -24,6 +25,7 @@ class Trepan
24
25
  # means hide none. Less than 0 means show
25
26
  # all stack entries.
26
27
  :hightlight => false, # Use terminal highlight?
28
+
27
29
  :maxlist => 10, # Number of source lines to list
28
30
  :maxstack => 10, # backtrace limit
29
31
  :maxstring => 150, # Strings which are larger than this
@@ -39,7 +41,7 @@ class Trepan
39
41
  :tracebuffer => false, # save events to a trace buffer.
40
42
  :user_cmd_dir => File.join(Trepan::HOME_DIR, 'tepanx', 'command'),
41
43
  # User command directory
42
- }
44
+ }
43
45
  end
44
46
  end
45
47
 
data/processor/eval.rb CHANGED
@@ -24,6 +24,19 @@ class Trepan
24
24
  end
25
25
  end
26
26
 
27
+ def eval_code(str, max_fake_filename)
28
+ obj = debug_eval(str, max_fake_filename)
29
+
30
+ # idx = @user_variables
31
+ # @user_variables += 1
32
+
33
+ # str = "$d#{idx}"
34
+ # Rubinius::Globals[str.to_sym] = obj
35
+ # msg "#{str} = #{obj.inspect}"
36
+ msg "#{obj.inspect}"
37
+ obj
38
+ end
39
+
27
40
  def exception_dump(e, stack_trace, backtrace)
28
41
  str = "#{e.class} Exception:\n\t#{e.message}"
29
42
  if stack_trace
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
1
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
2
  # For recording hook events in a buffer for review later. Make use of
3
3
  # Trace::Buffer for this prupose.
4
4
  require 'trace'
@@ -94,7 +94,8 @@ class Trepan
94
94
  mess += "\n\tVM offset #{item.pc_offset}"
95
95
  end
96
96
  unless same_loc
97
- text = LineCache::getline(container, location, @reload_on_change)
97
+ text = LineCache::getline(container, location,
98
+ :reload_on_change => @reload_on_change)
98
99
  mess += ":\n #{text.chomp}" if text
99
100
  end
100
101
  return container, location, mess
data/processor/frame.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
2
  require 'linecache'
3
+ require_relative '../app/complete'
3
4
  require_relative '../app/frame'
4
5
  class Trepan
5
6
  class CmdProcessor
@@ -51,6 +52,24 @@ class Trepan
51
52
  end
52
53
  end
53
54
 
55
+ def frame_low_high(direction)
56
+ stack_size = @top_frame.stack_size - @hide_level
57
+ if direction
58
+ low, high = [ @frame_index * -direction,
59
+ (stack_size - 1 - @frame_index) * direction ]
60
+ low, high = [high, low] if direction < 0
61
+ [low, high]
62
+ else
63
+ [-stack_size, stack_size-1]
64
+ end
65
+ end
66
+
67
+ def frame_complete(prefix, direction)
68
+ low, high = frame_low_high(direction)
69
+ ary = (low..high).map{|i| i.to_s}
70
+ Trepan::Complete.complete_token(ary, prefix)
71
+ end
72
+
54
73
  def frame_container(frame, canonicalize=true)
55
74
  container =
56
75
  if @remap_container.member?(frame.source_container)
data/processor/help.rb CHANGED
@@ -1,5 +1,25 @@
1
1
  # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
2
  class Trepan
3
+ # class SubHelp
4
+ # def initialize(name, dir)
5
+ # @name = name
6
+ # @dir = dir
7
+ # load_sub_help_files(dir)
8
+ # end
9
+
10
+ # def load_sub_help_files(dir)
11
+ # Dir.glob(dir, '*.txt').each do |txt|
12
+ # basename = File.basename(txt, '.txt')
13
+ # @list << basename
14
+ # end
15
+ # end if File.directory?(dir)
16
+
17
+ # def summary_help
18
+ # section "List of #{@name} help"
19
+ # msg @list
20
+ # end
21
+ # end
22
+
3
23
  module Help
4
24
 
5
25
  def abbrev_stringify(name, min_abbrev)
@@ -1,7 +1,11 @@
1
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
- # Trepan::CmdProcess that loads up debugger commands from builtin and
3
- # user directories.
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require 'tmpdir'
4
+
5
+ # Part of Trepan::CmdProcess that loads up debugger commands from
6
+ # builtin and user directories.
4
7
  # Sets @commands, @aliases, @macros
8
+ require_relative '../app/complete'
5
9
  class Trepan
6
10
  class CmdProcessor
7
11
 
@@ -21,8 +25,8 @@ class Trepan
21
25
  cmd_dirs = [ File.join(File.dirname(__FILE__), 'command') ]
22
26
  cmd_dirs << @settings[:user_cmd_dir] if @settings[:user_cmd_dir]
23
27
  cmd_dirs.each do |cmd_dir|
24
- load_debugger_commands(cmd_dir) if File.directory?(cmd_dir)
25
- end
28
+ load_debugger_commands(cmd_dir) if File.directory?(cmd_dir)
29
+ end
26
30
  end
27
31
 
28
32
  # Loads in debugger commands by require'ing each ruby file in the
@@ -31,7 +35,8 @@ class Trepan
31
35
  # is returned.
32
36
  def load_debugger_commands(file_or_dir)
33
37
  if File.directory?(file_or_dir)
34
- Dir.glob(File.join(file_or_dir, '*.rb')).each do |rb|
38
+ dir = File.expand_path(file_or_dir)
39
+ Dir.glob(File.join(dir, '*.rb')).each do |rb|
35
40
  # We use require so that multiple calls have no effect.
36
41
  require rb
37
42
  end
@@ -56,23 +61,6 @@ class Trepan
56
61
  end
57
62
  end
58
63
 
59
- # Instantiate a Trepan::Command and extract info: the NAME, ALIASES
60
- # and store the command in @commands.
61
- def setup_command(command)
62
- # Note: there is probably a non-eval way to instantiate the
63
- # command, but I don't know it. And eval works.
64
- klass = self.instance_eval("Trepan::Command::#{command}")
65
- cmd = klass.send(:new, self)
66
-
67
- # Add to list of commands and aliases.
68
- cmd_name = klass.const_get(:NAME)
69
- if klass.constants.member?(:ALIASES)
70
- aliases= klass.const_get(:ALIASES)
71
- aliases.each {|a| @aliases[a] = cmd_name}
72
- end
73
- @commands[cmd_name] = cmd
74
- end
75
-
76
64
  # Looks up cmd_array[0] in @commands and runs that. We do lots of
77
65
  # validity testing on cmd_array.
78
66
  def run_cmd(cmd_array)
@@ -95,10 +83,138 @@ class Trepan
95
83
  @commands[cmd_name].run(cmd_array)
96
84
  end
97
85
  end
86
+
87
+ def save_commands(opts)
88
+ save_filename = opts[:filename] ||
89
+ File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(['trepanning-save', '.txt'], nil))
90
+ begin
91
+ save_file = File.open(save_filename, 'w')
92
+ rescue => exc
93
+ errmsg("Can't open #{save_filename} for writing.")
94
+ errmsg("System reports: #{exc.inspect}")
95
+ return nil
96
+ end
97
+ save_file.puts "#\n# Commands to restore trepanning environment\n#\n"
98
+ @commands.each do |cmd_name, cmd_obj|
99
+ cmd_obj.save_command if cmd_obj.respond_to?(:save_command)
100
+ next unless cmd_obj.is_a?(Trepan::SubcommandMgr)
101
+ cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj|
102
+ save_file.puts subcmd_obj.save_command if
103
+ subcmd_obj.respond_to?(:save_command)
104
+ next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr)
105
+ subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj|
106
+ save_file.puts subsubcmd_obj.save_command if
107
+ subsubcmd_obj.respond_to?(:save_command)
108
+ end
109
+ end
110
+ end
111
+ save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
112
+ opts[:erase]
113
+ save_file.close
114
+
115
+ return save_filename
116
+ end
117
+
118
+ # Instantiate a Trepan::Command and extract info: the NAME, ALIASES
119
+ # and store the command in @commands.
120
+ def setup_command(command)
121
+ # Note: there is probably a non-eval way to instantiate the
122
+ # command, but I don't know it. And eval works.
123
+ klass = self.instance_eval("Trepan::Command::#{command}")
124
+ cmd = klass.send(:new, self)
125
+
126
+ # Add to list of commands and aliases.
127
+ cmd_name = klass.const_get(:NAME)
128
+ if klass.constants.member?(:ALIASES)
129
+ aliases= klass.const_get(:ALIASES)
130
+ aliases.each {|a| @aliases[a] = cmd_name}
131
+ end
132
+ @commands[cmd_name] = cmd
133
+ end
134
+
135
+ # Handle initial completion. We draw from the commands, aliases,
136
+ # and macros for completion. However we won't include aliases which
137
+ # are prefixes of other commands.
138
+ def complete(str, last_token)
139
+ next_blank_pos, token = Trepan::Complete.next_token(str, 0)
140
+ return [''] if token.empty? && !last_token.empty?
141
+ match_pairs = Trepan::Complete.complete_token_with_next(@commands,
142
+ token)
143
+ match_hash = {}
144
+ match_pairs.each do |pair|
145
+ match_hash[pair[0]] = pair[1]
146
+ end
147
+ alias_pairs = Trepan::Complete.
148
+ complete_token_filtered_with_next(@aliases, token, match_hash,
149
+ @commands)
150
+ match_pairs += alias_pairs
151
+ if str[next_blank_pos..-1].empty?
152
+ return match_pairs.map{|pair| pair[0]}.sort
153
+ else
154
+ alias_pairs.each do |pair|
155
+ match_hash[pair[0]] = pair[1]
156
+ end
157
+ end
158
+ if match_pairs.size > 1
159
+ # FIXME: figure out what to do here.
160
+ # Matched multiple items in the middle of the string
161
+ # We can't handle this so do nothing.
162
+ return []
163
+ # return match_pairs.map do |name, cmd|
164
+ # ["#{name} #{args[1..-1].join(' ')}"]
165
+ # end
166
+ end
167
+ # match_pairs.size == 1
168
+ next_complete(str, next_blank_pos, match_pairs[0][1], last_token)
169
+ end
170
+
171
+ def next_complete(str, next_blank_pos, cmd, last_token)
172
+ # debugger if 8 == next_blank_pos
173
+ next_blank_pos, token = Trepan::Complete.next_token(str, next_blank_pos)
174
+ return [] if token.empty? && !last_token.empty?
175
+
176
+ if cmd.respond_to?(:complete_token_with_next)
177
+ match_pairs = cmd.complete_token_with_next(token)
178
+ return [] if match_pairs.empty?
179
+ if str[next_blank_pos..-1].rstrip.empty? &&
180
+ (token.empty? || token == last_token)
181
+ return match_pairs.map { |completion, junk| completion }
182
+ else
183
+ if match_pairs.size == 1
184
+ return next_complete(str, next_blank_pos, match_pairs[0][1],
185
+ last_token)
186
+ else
187
+ # FIXME: figure out what to do here.
188
+ # Matched multiple items in the middle of the string
189
+ # We can't handle this so do nothing.
190
+ return []
191
+ end
192
+ end
193
+ elsif cmd.respond_to?(:complete)
194
+ matches = cmd.complete(token)
195
+ return [] if matches.empty?
196
+ if str[next_blank_pos..-1].rstrip.empty? &&
197
+ (token.empty? || token == last_token)
198
+ return matches
199
+ else
200
+ # FIXME: figure out what to do here.
201
+ # Matched multiple items in the middle of the string
202
+ # We can't handle this so do nothing.
203
+ return []
204
+ end
205
+ else
206
+ return []
207
+ end
208
+ end
98
209
  end
99
210
  end
100
211
  if __FILE__ == $0
101
- cmdproc = Trepan::CmdProcessor.new
212
+ class Trepan::CmdProcessor
213
+ def initialize(core, settings={})
214
+ end
215
+ end
216
+
217
+ cmdproc = Trepan::CmdProcessor.new(nil)
102
218
  cmddir = File.join(File.dirname(__FILE__), 'command')
103
219
  cmdproc.instance_variable_set('@settings', {})
104
220
  cmdproc.load_cmds_initialize
@@ -119,4 +235,7 @@ if __FILE__ == $0
119
235
  cmdproc.run_cmd('foo') # Invalid - not an Array
120
236
  cmdproc.run_cmd([]) # Invalid - empty Array
121
237
  cmdproc.run_cmd(['list', 5]) # Invalid - nonstring arg
238
+ p cmdproc.complete("d")
239
+ p cmdproc.complete("sho d")
240
+ p cmdproc.complete('')
122
241
  end