rbx-trepanning 0.0.7-universal-rubinius-1.2 → 0.0.8-universal-rubinius-1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/ChangeLog +236 -0
  2. data/NEWS +16 -0
  3. data/Rakefile +60 -11
  4. data/app/breakpoint.rb +5 -1
  5. data/app/brkptmgr.rb +5 -0
  6. data/app/cmd_parse.kpeg +225 -0
  7. data/app/cmd_parse.rb +209 -0
  8. data/app/cmd_parser.rb +1894 -0
  9. data/app/default.rb +0 -1
  10. data/app/method.rb +12 -8
  11. data/app/options.rb +2 -9
  12. data/app/validate.rb +2 -2
  13. data/bin/trepanx +3 -3
  14. data/lib/trepanning.rb +9 -6
  15. data/processor/breakpoint.rb +5 -19
  16. data/processor/command/alias.rb +4 -5
  17. data/processor/command/base/submgr.rb +2 -2
  18. data/processor/command/break.rb +44 -66
  19. data/processor/command/condition.rb +2 -0
  20. data/processor/command/continue.rb +11 -41
  21. data/processor/command/disassemble.rb +2 -0
  22. data/processor/command/eval.rb +20 -8
  23. data/processor/command/exit.rb +3 -2
  24. data/{doc → processor/command/help}/.gitignore +0 -0
  25. data/processor/command/help/command.txt +48 -0
  26. data/processor/command/help/filename.txt +40 -0
  27. data/processor/command/help/location.txt +37 -0
  28. data/processor/command/help.rb +52 -73
  29. data/processor/command/info_subcmd/breakpoints.rb +35 -13
  30. data/processor/command/info_subcmd/files.rb +34 -25
  31. data/processor/command/info_subcmd/frame.rb +67 -0
  32. data/processor/command/kill.rb +0 -1
  33. data/processor/command/restart.rb +8 -8
  34. data/processor/command/save.rb +58 -0
  35. data/processor/command/set_subcmd/trace_subcmd/buffer.rb +1 -1
  36. data/processor/command/set_subcmd/trace_subcmd/print.rb +1 -1
  37. data/processor/command/show.rb +7 -6
  38. data/processor/command/step.rb +16 -3
  39. data/processor/command/tbreak.rb +1 -1
  40. data/processor/disassemble.rb +1 -1
  41. data/processor/help.rb +20 -0
  42. data/processor/load_cmds.rb +53 -4
  43. data/processor/location.rb +47 -1
  44. data/processor/main.rb +4 -9
  45. data/processor/mock.rb +3 -3
  46. data/processor/running.rb +16 -17
  47. data/processor/validate.rb +171 -159
  48. data/rbx-trepanning.gemspec +1 -1
  49. data/test/example/debugger-stop.rb +16 -0
  50. data/test/functional/test-break-name.rb +1 -1
  51. data/test/functional/test-eval.rb +115 -0
  52. data/test/functional/test-tbreak.rb +1 -1
  53. data/test/integration/helper.rb +5 -2
  54. data/test/unit/cmd-helper.rb +1 -1
  55. data/test/unit/test-app-cmd_parse.rb +97 -0
  56. data/test/unit/test-app-cmd_parser.rb +22 -0
  57. data/test/unit/test-app-options.rb +1 -0
  58. data/test/unit/test-app-validate.rb +2 -2
  59. data/test/unit/test-cmd-break.rb +47 -5
  60. data/test/unit/test-completion.rb +2 -1
  61. data/test/unit/test-proc-location.rb +11 -0
  62. data/test/unit/test-proc-validate.rb +68 -30
  63. metadata +26 -11
  64. data/doc/debugger.html +0 -108
@@ -1,20 +1,21 @@
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 'rubygems'; require 'require_relative'
4
4
  require_relative 'base/submgr'
5
5
 
6
6
  class Trepan::Command::ShowCommand < Trepan::SubcommandMgr
7
7
  unless defined?(HELP)
8
- HELP =
9
- 'Generic command for showing things about the debugger. You can
8
+ NAME = File.basename(__FILE__, '.rb')
9
+ HELP = <<-HELP
10
+ Generic command for showing things about the debugger. You can
10
11
  give unique prefix of the name of a subcommand to get information
11
12
  about just that subcommand.
12
13
 
13
- Type "show" for a list of "show" subcommands and what they do.
14
- Type "help show *" for just a list of "show" subcommands.'
14
+ Type "#{NAME}" for a list of "show" subcommands and what they do.
15
+ Type "help #{NAME} *" for just a list of "show" subcommands.
16
+ HELP
15
17
 
16
18
  CATEGORY = 'status'
17
- NAME = File.basename(__FILE__, '.rb')
18
19
  NEED_STACK = false
19
20
  SHORT_HELP = 'Show parts of the debugger environment'
20
21
  end
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'; require 'require_relative'
2
2
  require_relative 'base/cmd'
3
+ require_relative '../../app/condition'
3
4
  require_relative '../stepping'
4
5
 
5
6
  class Trepan::Command::StepCommand < Trepan::Command
@@ -9,6 +10,7 @@ class Trepan::Command::StepCommand < Trepan::Command
9
10
  NAME = File.basename(__FILE__, '.rb')
10
11
  HELP = <<-HELP
11
12
  #{NAME}[+|-] [into] [count]
13
+ #{NAME} until EXPRESSION
12
14
  #{NAME} over [args..]
13
15
  #{NAME} out [args..]
14
16
 
@@ -26,6 +28,7 @@ Examples:
26
28
  #{NAME} 5/5+0 # same as above
27
29
  #{NAME}+ # same but force stopping on a new line
28
30
  #{NAME}- # same but force stopping on a new line a new frame added
31
+ #{NAME} until a > b
29
32
  #{NAME} over # same as 'next'
30
33
  #{NAME} out # same as 'finish'
31
34
 
@@ -44,15 +47,25 @@ See also the commands:
44
47
  'into' => 'step',
45
48
  }
46
49
 
47
- def run(args)
50
+ include Trepan::Condition
51
+ # This method runs the command
52
+ def run(args) # :nodoc
53
+ condition = nil
54
+ opts = {}
48
55
  if args.size == 1
49
56
  step_count = 1
50
- opts = {}
51
57
  else
52
58
  replace_cmd = Keyword_to_related_cmd[args[1]]
53
59
  if replace_cmd
54
60
  cmd = @proc.commands[replace_cmd]
55
61
  return cmd.run([replace_cmd] + args[2..-1])
62
+ elsif 'until' == args[1]
63
+ try_condition = args[2..-1].join(' ')
64
+ if valid_condition?(try_condition)
65
+ condition = try_condition
66
+ opts[:different_pos] = false
67
+ step_count = 0
68
+ end
56
69
  else
57
70
  step_str = args[1]
58
71
  opts = @proc.parse_next_step_suffix(args[0])
@@ -67,7 +80,7 @@ See also the commands:
67
80
  end
68
81
  end
69
82
 
70
- @proc.step('step', step_count, opts)
83
+ @proc.step('step', step_count, opts, condition)
71
84
  end
72
85
  end
73
86
 
@@ -3,7 +3,7 @@ require_relative './base/cmd'
3
3
  require_relative 'break'
4
4
 
5
5
  class Trepan::Command::SetTempBreakpointCommand <
6
- Trepan::Command::SetBreakpointCommand
6
+ Trepan::Command::BreakCommand
7
7
  ALIASES = %w(tb tbrk)
8
8
  CATEGORY = 'breakpoints'
9
9
  NAME = File.basename(__FILE__, '.rb')
@@ -10,7 +10,7 @@ class Trepan
10
10
  start = meth.first_ip_on_line(line)
11
11
  fin = meth.first_ip_on_line(line+1)
12
12
 
13
- if fin == -1
13
+ if !fin || fin == -1
14
14
  fin = meth.iseq.size
15
15
  end
16
16
 
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,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require 'tmpdir'
3
4
 
4
5
  # Part of Trepan::CmdProcess that loads up debugger commands from
5
6
  # builtin and user directories.
@@ -62,6 +63,23 @@ class Trepan
62
63
  end
63
64
  end
64
65
 
66
+ # Instantiate a Trepan::Command and extract info: the NAME, ALIASES
67
+ # and store the command in @commands.
68
+ def setup_command(command)
69
+ # Note: there is probably a non-eval way to instantiate the
70
+ # command, but I don't know it. And eval works.
71
+ klass = self.instance_eval("Trepan::Command::#{command}")
72
+ cmd = klass.send(:new, self)
73
+
74
+ # Add to list of commands and aliases.
75
+ cmd_name = klass.const_get(:NAME)
76
+ if klass.constants.member?(:ALIASES)
77
+ aliases= klass.const_get(:ALIASES)
78
+ aliases.each {|a| @aliases[a] = cmd_name}
79
+ end
80
+ @commands[cmd_name] = cmd
81
+ end
82
+
65
83
  # Looks up cmd_array[0] in @commands and runs that. We do lots of
66
84
  # validity testing on cmd_array.
67
85
  def run_cmd(cmd_array)
@@ -85,6 +103,37 @@ class Trepan
85
103
  end
86
104
  end
87
105
 
106
+ def save_commands(opts)
107
+ save_filename = opts[:filename] ||
108
+ File.join(Dir.tmpdir, "trepanning-save-#{$$}.txt")
109
+ begin
110
+ save_file = File.open(save_filename, 'w')
111
+ rescue => exc
112
+ errmsg("Can't open #{save_filename} for writing.")
113
+ errmsg("System reports: #{exc.inspect}")
114
+ return nil
115
+ end
116
+ save_file.puts "#\n# Commands to restore trepanning environment\n#\n"
117
+ @commands.each do |cmd_name, cmd_obj|
118
+ cmd_obj.save_command if cmd_obj.respond_to?(:save_command)
119
+ next unless cmd_obj.is_a?(Trepan::SubcommandMgr)
120
+ cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj|
121
+ save_file.puts subcmd_obj.save_command if
122
+ subcmd_obj.respond_to?(:save_command)
123
+ next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr)
124
+ subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj|
125
+ save_file.puts subsubcmd_obj.save_command if
126
+ subsubcmd_obj.respond_to?(:save_command)
127
+ end
128
+ end
129
+ end
130
+ save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
131
+ opts[:erase]
132
+ save_file.close
133
+
134
+ return save_filename
135
+ end
136
+
88
137
  # Handle initial completion. We draw from the commands, aliases,
89
138
  # and macros for completion. However we won't include aliases which
90
139
  # are prefixes of other commands.
@@ -117,7 +166,7 @@ class Trepan
117
166
  # ["#{name} #{args[1..-1].join(' ')}"]
118
167
  # end
119
168
  end
120
- # match_pairs.size == 1
169
+ # match_pairs.size <= 1
121
170
  next_complete(str, next_blank_pos, match_pairs[0][1], last_token)
122
171
  end
123
172
 
@@ -187,7 +236,7 @@ if __FILE__ == $0
187
236
  cmdproc.run_cmd('foo') # Invalid - not an Array
188
237
  cmdproc.run_cmd([]) # Invalid - empty Array
189
238
  cmdproc.run_cmd(['list', 5]) # Invalid - nonstring arg
190
- p cmdproc.complete("d")
191
- p cmdproc.complete("sho d")
192
- p cmdproc.complete('')
239
+ p cmdproc.complete("d", 'd')
240
+ p cmdproc.complete("sho d", 'd')
241
+ p cmdproc.complete('', '')
193
242
  end
@@ -1,6 +1,8 @@
1
1
  # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require 'pathname' # For cleanpath
3
+ require 'rubygems';
2
4
  require 'linecache'
3
- require 'rubygems'; require 'require_relative'
5
+ require 'require_relative'
4
6
  require_relative 'disassemble'
5
7
  require_relative 'msg'
6
8
  require_relative 'frame'
@@ -12,6 +14,13 @@ class Trepan
12
14
  @reload_on_change = nil
13
15
  end
14
16
 
17
+ def canonic_file(filename)
18
+ # For now we want resolved filenames
19
+ @settings[:basename] ? File.basename(filename) :
20
+ # Cache this?
21
+ File.expand_path(Pathname.new(filename).cleanpath.to_s)
22
+ end
23
+
15
24
  # Return the text to the current source line.
16
25
  # FIXME: loc_and_text should call this rather than the other
17
26
  # way around.
@@ -66,10 +75,12 @@ class Trepan
66
75
  {:reload_on_change => @reload_on_change,
67
76
  :output => @settings[:highlight]
68
77
  })
78
+
69
79
  vm_location = @frame.vm_location
70
80
  filename = vm_location.method.active_path
71
81
  line_no = vm_location.line
72
82
  static = vm_location.static_scope
83
+ opts[:compiled_method] = top_scope(@frame.method)
73
84
 
74
85
  if @frame.eval?
75
86
  file = LineCache::map_script(static.script)
@@ -175,3 +186,38 @@ class Trepan
175
186
 
176
187
  end
177
188
  end
189
+
190
+ if __FILE__ == $0 && caller.size == 0 && ARGV.size > 0
191
+ # Demo it.
192
+ require 'thread_frame'
193
+ require_relative 'frame'
194
+ require_relative '../app/mock'
195
+ require_relative 'main' # Have to include before defining CmdProcessor!
196
+ # FIXME
197
+ class Trepan::CmdProcessor
198
+ def errmsg(msg)
199
+ puts msg
200
+ end
201
+ def print_location
202
+ puts "#{@frame.source_container} #{frame.source_location[0]}"
203
+ end
204
+ end
205
+
206
+ proc = Trepan::CmdProcessor.new(Trepan::MockCore.new())
207
+ proc.instance_variable_set('@settings', {})
208
+ proc.frame_initialize
209
+ #proc.frame_setup(RubyVM::ThreadFrame.current)
210
+ proc.frame_initialize
211
+
212
+ proc.location_initialize
213
+ puts proc.canonic_file(__FILE__)
214
+ proc.instance_variable_set('@settings', {:basename => true})
215
+ puts proc.canonic_file(__FILE__)
216
+ puts proc.current_source_text
217
+ xx = eval <<-END
218
+ proc.frame_initialize
219
+ ##proc.frame_setup(RubyVM::ThreadFrame.current)
220
+ proc.location_initialize
221
+ proc.current_source_text
222
+ END
223
+ end
data/processor/main.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  # command class and debugger command objects are pulled in from here.
4
4
 
5
5
  require 'set'
6
- require 'pathname' # For cleanpath
7
6
 
8
7
  require 'rubygems'; require 'require_relative'
9
8
  ## %w(default display eventbuf eval load_cmds location frame hook msg
@@ -137,13 +136,6 @@ class Trepan
137
136
  [container[0], canonic_file(container[1])]
138
137
  end
139
138
 
140
- def canonic_file(filename)
141
- # For now we want resolved filenames
142
- @settings[:basename] ? File.basename(filename) :
143
- # Cache this?
144
- Pathname.new(filename).cleanpath.to_s
145
- end
146
-
147
139
  def compute_prompt
148
140
  "(#{@settings[:prompt]}): "
149
141
  end
@@ -213,6 +205,9 @@ class Trepan
213
205
  quit('exit!')
214
206
  return true
215
207
  end
208
+ rescue Exception => exc
209
+ errmsg("Internal debugger error in read: #{exc.inspect}")
210
+ exception_dump(exc, @settings[:debugexcept], $!.backtrace)
216
211
  end
217
212
  end
218
213
  run_command(@current_command)
@@ -235,7 +230,7 @@ class Trepan
235
230
  @last_pos = [@frame.vm_location, @stack_size, @current_thread, @event]
236
231
  else
237
232
  if stepping_skip? # || @stack_size <= @hide_level
238
- step(@return_to_program, @step_count)
233
+ step(@return_to_program, @step_count, {}, @stop_condition)
239
234
  return true
240
235
  elsif @event == 'start'
241
236
  step('step', 0)
data/processor/mock.rb CHANGED
@@ -28,12 +28,12 @@ module MockDebugger
28
28
  attr_reader :cmd_argstr, :cmd_name, :vm_locations, :current_frame,
29
29
  :debugee_thread, :completion_proc
30
30
 
31
- def initialize(settings={})
31
+ def initialize(settings={:start_frame=>1})
32
32
  @before_cmdloop_hooks = []
33
33
  @settings = Trepan::DEFAULT_SETTINGS.merge(settings)
34
34
  @intf = [Trepan::UserInterface.new(nil, nil,
35
35
  :history_save=>false)]
36
- @vm_locations = Rubinius::VM.backtrace(1, true)
36
+ @vm_locations = Rubinius::VM.backtrace(settings[:start_frame], true)
37
37
  @current_frame = Trepan::Frame.new(self, 0, @vm_locations[0])
38
38
  @debugee_thread = Thread.current
39
39
  @frames = []
@@ -66,7 +66,7 @@ module MockDebugger
66
66
  dbgr = Trepan.new
67
67
  dbgr.debugger
68
68
  else
69
- dbgr = MockDebugger.new
69
+ dbgr = MockDebugger.new(:start_frame=>2)
70
70
  end
71
71
 
72
72
  cmdproc = Trepan::CmdProcessor.new(dbgr)
data/processor/running.rb CHANGED
@@ -193,24 +193,23 @@ class Trepan
193
193
  end
194
194
 
195
195
  @last_pos[2] = new_pos[2] if 'nostack' == @different_pos
196
- condition_met = @step_count == 0
197
-
198
- # if @stop_condition
199
- # puts 'stop_cond' if @settings[:'debugskip']
200
- # debug_eval_no_errmsg(@stop_condition)
201
- # elsif @to_method
202
- # puts "method #{@frame.method} #{@to_method}" if
203
- # @settings[:'debugskip']
204
- # @frame.method == @to_method
205
- # else
206
- # puts 'uncond' if @settings[:'debugskip']
207
- # true
208
- # end
196
+ condition_met =
197
+ if @stop_condition
198
+ puts "stop_cond #{@stop_condition}" if @settings[:'debugskip']
199
+ debug_eval_no_errmsg(@stop_condition)
200
+ elsif @to_method
201
+ puts "method #{@frame.method} #{@to_method}" if
202
+ @settings[:'debugskip']
203
+ @frame.method == @to_method
204
+ else
205
+ puts 'uncond' if @settings[:'debugskip']
206
+ @step_count == 0
207
+ end
209
208
 
210
- # msg("condition_met: #{condition_met}, last: #{@last_pos}, " +
211
- # "new: #{new_pos}, different #{@different_pos.inspect}") if
212
- # @settings[:'debugskip']
213
-
209
+ msg("condition_met: #{condition_met}, last: #{@last_pos}, " +
210
+ "new: #{new_pos}, different #{@different_pos.inspect}") if
211
+ @settings[:'debugskip']
212
+
214
213
  should_skip = ((@last_pos[0..3] == new_pos[0..3] && @different_pos) ||
215
214
  !condition_met)
216
215