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
data/app/default.rb CHANGED
@@ -22,7 +22,6 @@ class Trepan
22
22
 
23
23
  :restart_argv => Rubinius::OS_ARGV,
24
24
  # Command run when "restart" is given.
25
- :restore_profile => nil, # Profile used to set/restore debugger state
26
25
  :server => false, # Out-of-process debugging?
27
26
  :skip_loader => false, # If run via -Xdebug or trepanx
28
27
  # command-line we need this to skip
data/app/method.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  module Trepanning
3
3
  module Method
4
4
 
5
+ module_function
5
6
  ## FIXME: until the next two routines find their way back into
6
7
  ## Rubinius::CompiledMethod...
7
8
  ##
@@ -23,7 +24,6 @@ module Trepanning
23
24
  end
24
25
  return nil
25
26
  end
26
- module_function :locate_line_in_cm
27
27
 
28
28
  ## FIXME: Try using Routine in Rubinius now.
29
29
  ##
@@ -54,7 +54,6 @@ module Trepanning
54
54
  # No child method is a match - fail
55
55
  return nil
56
56
  end
57
- module_function :locate_line
58
57
 
59
58
  def lines_of_method(cm)
60
59
  lines = []
@@ -63,7 +62,6 @@ module Trepanning
63
62
  end
64
63
  return lines
65
64
  end
66
- module_function :lines_of_method
67
65
 
68
66
  # Return true if ip is the start of some instruction in meth.
69
67
  # FIXME: be more stringent.
@@ -71,7 +69,6 @@ module Trepanning
71
69
  size = cm.lines.size
72
70
  ip >= 0 && ip < cm.lines[size-1]
73
71
  end
74
- module_function :valid_ip?
75
72
 
76
73
  # Returns a CompiledMethod for the specified line. We search the
77
74
  # current method +meth+ and then up the parent scope. If we hit
@@ -84,13 +81,11 @@ module Trepanning
84
81
  end
85
82
 
86
83
  lines = lines_of_method(cm)
87
- ## p ['++++1', cm, lines]
88
84
  return cm if lines.member?(line)
89
85
  scope = cm.scope
90
86
  return nil unless scope.current_script
91
87
  cm = scope.current_script.compiled_method
92
88
  lines = lines_of_method(cm)
93
- ## p ['++++2', cm, lines]
94
89
  until lines.member?(line) do
95
90
  child = scope
96
91
  scope = scope.parent
@@ -103,11 +98,19 @@ module Trepanning
103
98
  end
104
99
  cm = scope.current_script.compiled_method
105
100
  lines = lines_of_method(cm)
106
- ## p ['++++3', cm, lines]
107
101
  end
108
102
  return cm
109
103
  end
110
- module_function :find_method_with_line
104
+
105
+ def top_scope(cm)
106
+ scope = cm.scope
107
+ while true do
108
+ scope = scope.parent
109
+ break unless scope && scope.current_script
110
+ cm = scope.current_script.compiled_method
111
+ end
112
+ cm
113
+ end
111
114
  end
112
115
 
113
116
  end
@@ -165,6 +168,7 @@ if __FILE__ == $0
165
168
  p lines_of_method(cm)
166
169
  find_line(line)
167
170
  p find_method_with_line(cm, line+2)
171
+ puts "top scope: #{top_scope(cm)}"
168
172
  ip = locate_line( __LINE__, cm)[1]
169
173
  puts "Line #{__LINE__} has ip #{ip}"
170
174
  [-1, 0, 10, ip, 10000].each do |i|
data/app/options.rb CHANGED
@@ -9,7 +9,7 @@ class Trepan
9
9
  require 'rubygems'; require 'require_relative'
10
10
  require_relative 'default'
11
11
 
12
- Trepan::VERSION = '0.0.7'
12
+ Trepan::VERSION = '0.0.8'
13
13
  Trepan::PROGRAM = 'trepanx'
14
14
 
15
15
  def self.show_version
@@ -82,13 +82,6 @@ EOB
82
82
  |num|
83
83
  options[:port] = num
84
84
  end
85
- opts.on("--restore PROFILE", String,
86
- "Restore debugger state using PROFILE") do |profile|
87
- if File.readable?(profile)
88
- options[:restore_profile] = profile
89
- stderr.puts "Debugger command file #{profile} is not readable. --restore option ignored."
90
- end
91
- end
92
85
  opts.on('--server',
93
86
  "Set up for out-of-process debugging") do
94
87
  if options[:client]
@@ -98,7 +91,7 @@ EOB
98
91
  end
99
92
  end
100
93
  opts.on('--[no-]highlight',
101
- "Use [no] syntax highligh output") do |v|
94
+ "Use [no] syntax highlight output") do |v|
102
95
  options[:highlight] = ((v) ? :term : nil)
103
96
  end
104
97
  opts.on('--[no-]readline',
data/app/validate.rb CHANGED
@@ -5,7 +5,7 @@ class Trepan
5
5
  def line_or_ip(arg_str)
6
6
  arg=arg_str.dup
7
7
  is_ip =
8
- if 'o' == arg[0..0].downcase
8
+ if '@' == arg[0..0]
9
9
  arg[0] = ''
10
10
  true
11
11
  else
@@ -24,7 +24,7 @@ end
24
24
 
25
25
  if __FILE__ == $0
26
26
  include Trepan::Validate
27
- %w(o1 O2 oink 1 12 -12).each do |arg|
27
+ %w(@1 oink 1 12 -12).each do |arg|
28
28
  puts "line_or_ip(#{arg})=#{line_or_ip(arg).inspect}"
29
29
  end
30
30
  end
data/bin/trepanx CHANGED
@@ -50,9 +50,9 @@ if File.basename(__FILE__) == File.basename($0)
50
50
  end
51
51
  end
52
52
 
53
- program_to_debug = ARGV.shift
54
- program_to_debug = whence_file(program_to_debug) unless
55
- File.exist?(program_to_debug)
53
+ program_to_debug = (Trepan::PROG_UNRESOLVED_SCRIPT = ARGV.shift).dup
54
+ program_to_debug = whence_file(Trepan::PROG_UNRESOLVED_SCRIPT) unless
55
+ File.exist?(Trepan::PROG_UNRESOLVED_SCRIPT)
56
56
  Trepan::PROG_SCRIPT = program_to_debug
57
57
 
58
58
  opts = {}
data/lib/trepanning.rb CHANGED
@@ -124,8 +124,6 @@ class Trepan
124
124
 
125
125
  # Run user debugger command startup files.
126
126
  add_startup_files unless @settings[:nx]
127
- add_command_file(@settings[:restore_profile]) if
128
- @settings[:restore_profile] && File.readable?(@settings[:restore_profile])
129
127
  end
130
128
 
131
129
  # The method is called when we want to do debugger command completion
@@ -155,7 +153,7 @@ class Trepan
155
153
  def skip_loader
156
154
  cmds =
157
155
  if @settings[:skip_loader] == :Xdebug
158
- ['continue Rubinius::CodeLoader#load_script',
156
+ ['continue Rubinius::CodeLoader.load_script',
159
157
  'continue 67',
160
158
  # 'set kernelstep off', # eventually would like 'on'
161
159
  'step', 'set hidelevel -1'
@@ -197,7 +195,7 @@ class Trepan
197
195
  # Startup the debugger, skipping back +offset+ frames. This lets you start
198
196
  # the debugger straight into callers method.
199
197
  #
200
- def start(settings = {:immediate => false})
198
+ def debugger(settings = {:immediate => false})
201
199
  @settings = @settings.merge(settings)
202
200
  skip_loader if @settings[:skip_loader]
203
201
  spinup_thread
@@ -206,6 +204,12 @@ class Trepan
206
204
  @processor.hidelevels[@thread] = @settings[:hide_level]
207
205
  end
208
206
 
207
+ # unless defined?(PROG_UNRESOLVED_SCRIPT)
208
+ # # We may later do more sophisticated things...
209
+ # Trepan.const_set('PROG_UNRESOLVED_SCRIPT',
210
+ # Rubinius::OS_ARGV.index($0) ? $0 : nil)
211
+ # end
212
+
209
213
  process_cmdfile_setting(settings)
210
214
 
211
215
  # Feed info to the debugger thread!
@@ -225,8 +229,7 @@ class Trepan
225
229
  Thread.current.set_debugger_thread @thread
226
230
  self
227
231
  end
228
- # ruby-debug compatibility
229
- alias debugger start
232
+ alias start debugger
230
233
 
231
234
  def stop(settings = {})
232
235
  @processor.finalize
@@ -45,8 +45,9 @@ class Trepan
45
45
  bp
46
46
  end
47
47
 
48
- def set_breakpoint_method(descriptor, meth, line=nil, ip=nil,
49
- opts={:event => 'brkpt',:temp => false})
48
+ def set_breakpoint_method(meth, line=nil, ip=nil,
49
+ opts={:event => 'brkpt', :negate=>false,
50
+ :temp => false})
50
51
  cm =
51
52
  if meth.kind_of?(Method) || meth.kind_of?(UnboundMethod)
52
53
  meth.executable
@@ -60,7 +61,7 @@ class Trepan
60
61
  end
61
62
 
62
63
  if line
63
- ip = cm.first_ip_on_line(line)
64
+ ip = cm.first_ip_on_line(line, -2)
64
65
 
65
66
  unless ip
66
67
  errmsg "Unknown line '#{line}' in method '#{cm.name}'"
@@ -74,7 +75,7 @@ class Trepan
74
75
  # def lines without code will have value -1.
75
76
  ip = 0 if -1 == ip
76
77
 
77
- bp = @brkpts.add(descriptor, cm, ip, line, @brkpts.max+1, opts)
78
+ bp = @brkpts.add(meth.name, cm, ip, line, @brkpts.max+1, opts)
78
79
  bp.activate
79
80
  msg("Set %sbreakpoint #{bp.id}: #{meth.name}() at #{bp.location}" %
80
81
  (opts[:temp] ? 'temporary ' : ''))
@@ -144,21 +145,6 @@ class Trepan
144
145
  return true
145
146
  end
146
147
 
147
- # MRI 1.9.2 code
148
- # # Enable or disable a breakpoint given its breakpoint number.
149
- # def en_disable_breakpoint_by_number(bpnum, do_enable=true)
150
- # bp = breakpoint_find(bpnum)
151
- # return false unless bp
152
-
153
- # enable_disable = do_enable ? 'en' : 'dis'
154
- # if bp.enabled? == do_enable
155
- # errmsg('Breakpoint %d previously %sabled.' %
156
- # [bpnum, enable_disable])
157
- # return false
158
- # end
159
- # bp.enabled = do_enable
160
- # return true
161
- # end
162
148
  end
163
149
  end
164
150
 
@@ -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 'rubygems'; require 'require_relative'
3
3
  require_relative 'base/cmd'
4
4
 
@@ -11,12 +11,11 @@ class Trepan::Command::AliasCommand < Trepan::Command
11
11
 
12
12
  Add an alias for a COMMAND
13
13
 
14
- See also 'unalias'.
14
+ See also 'unalias' and 'show #{NAME}'.
15
15
  HELP
16
16
 
17
17
  CATEGORY = 'support'
18
18
  MAX_ARGS = 2 # Need at most this many
19
- NAME = File.basename(__FILE__, '.rb')
20
19
  NEED_STACK = true
21
20
  SHORT_HELP = 'Add an alias for a debugger command'
22
21
  end
@@ -24,9 +23,9 @@ See also 'unalias'.
24
23
  # Run command.
25
24
  def run(args)
26
25
  if args.size == 1
27
- @proc.commands['show'].run(%w(show alias))
26
+ @proc.commands['show'].run(%W(show #{NAME}))
28
27
  elsif args.size == 2
29
- @proc.commands['show'].run(%W(show alias #{args[1]}))
28
+ @proc.commands['show'].run(%W(show #{NAME} #{args[1]}))
30
29
  else
31
30
  junk, al, command = args
32
31
  old_command = @proc.aliases[al]
@@ -70,8 +70,8 @@ class Trepan::SubcommandMgr < Trepan::Command
70
70
  subcmd_class = Trepan::SubSubcommand.const_get(name)
71
71
  begin
72
72
  cmd = subcmd_class.send(:new, self, parent)
73
- rescue
74
- puts "Subcmd #{name} is bad"
73
+ rescue Exception => exc
74
+ puts "Subcmd #{name} in #{parent.name.inspect} is bad: #{exc}"
75
75
  end
76
76
  @subcmds.add(cmd)
77
77
  end
@@ -1,82 +1,47 @@
1
- # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
1
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
2
  require 'rubygems'; require 'require_relative'
3
3
  require_relative './base/cmd'
4
4
 
5
- class Trepan::Command::SetBreakpointCommand < Trepan::Command
5
+ class Trepan::Command::BreakCommand < Trepan::Command
6
6
 
7
7
  ALIASES = %w(b brk)
8
8
  CATEGORY = 'breakpoints'
9
9
  NAME = File.basename(__FILE__, '.rb')
10
10
  HELP = <<-HELP
11
- #{NAME}
12
- #{NAME} [line number|offset]
13
- #{NAME} Class[.#]method[:line-or-offset]
11
+ #{NAME} LOCATION [ {if|unless} CONDITION ]
14
12
 
15
- Sets a breakpoint. In the first form, a breakpoint is set at the
16
- current line you are stopped at. In the second form, you give a line
17
- number or an offset. An offset is a number that is prefaced with 'O'
18
- or 'o' and represents a Rubinius VM PC offset.
19
-
20
- The current method name is used for the start of the search. If a line
21
- number is given and the line number is not found in that method,
22
- enclosing scopes are searched for the line.
23
-
24
- The last form is the most explicit. Use '#' to specify an instance
25
- method and '.' to specify a class method. If a line number or offset
26
- is omitted, we use the first line of the method.
13
+ Set a breakpoint. In the second form where CONDITIOn is given, the
14
+ condition is evaluated in the context of the position. We stop only If
15
+ CONDITION evalutes to non-false/nil and the "if" form used, or it is
16
+ false and the "unless" form used.\
27
17
 
28
18
  Examples:
19
+ #{NAME}
20
+ #{NAME} 10 # set breakpoint on line 10
21
+ #{NAME} 10 if 1 == a # like above but only if a is equal to 1
22
+ #{NAME} 10 unless 1 == a # like above but only if a is equal to 1
23
+ #{NAME} me.rb:10
24
+ #{NAME} @20 # set breakpoint VM Instruction Sequence offset 20
25
+ #{NAME} Kernel.pp # Set a breakpoint at the beginning of Kernel.pp
29
26
 
30
- #{NAME} # set breakpoint at the current line
31
- #{NAME} 5 # set breakpoint on line 5
32
- #{NAME} O5 # set breakpoint at offset 5
33
- #{NAME} o5 # same as above
34
- #{NAME} Array#pop::3 # Set break at instance method 'pop' in Array, line 3
35
- #{NAME} Trepan.start:3 # Set break in class method 'start' of Trepan, line 3
36
- #{NAME} Trepan.start:o3 # Same as above but at offset 3, not line 3.
37
- #{NAME} Trepan.start # Set break in class method 'start' of Trepan
38
-
39
- See also 'tbreak', 'info breakpoint', and 'delete'.
27
+ See also condition, continue and "help location".
40
28
  HELP
41
29
  SHORT_HELP = 'Set a breakpoint at a point in a method'
42
30
 
31
+ # This method runs the command
43
32
  def run(args, temp=false)
44
- arg_str = args[1..-1].join(' ')
45
-
46
- describe, klass_name, which, name, line, ip =
47
- @proc.breakpoint_position(args[1..-1])
48
- event = temp ? 'tbrkpt' : 'brkpt'
49
- opts={:event => event, :temp => temp}
50
- if name.kind_of?(Rubinius::CompiledMethod)
51
- bp = @proc.set_breakpoint_method(describe, name, line, ip, opts)
52
- else
53
- return unless klass_name
54
-
55
- begin
56
- klass = @proc.debug_eval(klass_name, settings[:maxstring])
57
- rescue NameError
58
- errmsg "Unable to find class/module: #{klass_name}"
59
- ask_deferred klass_name, which, name, line
60
- return
61
- end
62
-
63
- begin
64
- if which == "#"
65
- method = klass.instance_method(name)
66
- else
67
- method = klass.method(name)
68
- end
69
- rescue NameError
70
- errmsg "Unable to find method '#{name}' in #{klass}"
71
- ask_deferred klass_name, which, name, line
72
- return
73
- end
74
33
 
75
- bp = @proc.set_breakpoint_method(arg_str.strip, method, line, ip, opts)
34
+ arg_str = args.size == 1 ? @proc.frame.line.to_s : @proc.cmd_argstr
35
+ cm, line, ip, condition, negate =
36
+ @proc.breakpoint_position(arg_str, true)
37
+ if cm
38
+ event = temp ? 'tbrkpt' : 'brkpt'
39
+ opts={:event => event, :temp => temp, :condition => condition,
40
+ :negate => negate}
41
+ bp = @proc.set_breakpoint_method(cm, line, ip, opts)
42
+ bp.set_temp! if temp
43
+ return bp
76
44
  end
77
-
78
- bp.set_temp! if temp
79
- return bp
80
45
  end
81
46
 
82
47
  def ask_deferred(klass_name, which, name, line)
@@ -92,9 +57,22 @@ end
92
57
  if __FILE__ == $0
93
58
  require_relative '../mock'
94
59
  dbgr, cmd = MockDebugger::setup
95
- cmd.run([cmd.name])
96
- # require 'trepanning'
97
- # Trepan.start(:set_restart => true)
98
- cmd.run([cmd.name, __LINE__.to_s])
99
- cmd.run([cmd.name, 'foo'])
60
+ # require_relative '../../lib/trepanning'
61
+ def run_cmd(cmd, args)
62
+ cmd.proc.instance_variable_set('@cmd_argstr', args[1..-1].join(' '))
63
+ cmd.run(args)
64
+ end
65
+
66
+ run_cmd(cmd, [cmd.name])
67
+ run_cmd(cmd, [cmd.name, __LINE__.to_s])
68
+
69
+ def foo
70
+ 5
71
+ end
72
+ run_cmd(cmd, [cmd.name, 'foo', (__LINE__-2).to_s])
73
+ run_cmd(cmd, [cmd.name, 'foo'])
74
+ run_cmd(cmd, [cmd.name, "MockDebugger::setup"])
75
+ require 'irb'
76
+ run_cmd(cmd, [cmd.name, "IRB.start"])
77
+ run_cmd(cmd, [cmd.name, 'foo93'])
100
78
  end
@@ -21,6 +21,8 @@ made unconditional.
21
21
  Examples:
22
22
  #{NAME} 5 x > 10 # Breakpoint 5 now has condition x > 10
23
23
  #{NAME} 5 # Remove above condition
24
+
25
+ See also "break", "enable" and "disable".
24
26
  HELP
25
27
 
26
28
  ALIASES = %w(cond)
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
1
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
2
  require 'rubygems'; require 'require_relative'
3
3
  require_relative 'base/cmd'
4
4
  require_relative '../stepping'
@@ -7,7 +7,7 @@ class Trepan::Command::ContinueCommand < Trepan::Command
7
7
  unless defined?(HELP)
8
8
  NAME = File.basename(__FILE__, '.rb')
9
9
  HELP = <<-HELP
10
- #{NAME} [breakpoint-position]
10
+ #{NAME} [LOCATION]
11
11
 
12
12
  Leave the debugger loop and continue execution. Subsequent entry to
13
13
  the debugger however may occur via breakpoints or explicit calls, or
@@ -24,7 +24,7 @@ Examples:
24
24
  #{NAME} gcd # continue to first instruction of method gcd
25
25
  #{NAME} IRB.start o7 # continue to IRB.start offset 7
26
26
 
27
- See also 'step', 'next', 'finish', and 'nexti' commands.
27
+ See also 'step', 'next', 'finish', 'nexti' commands and "help location".
28
28
  HELP
29
29
 
30
30
  ALIASES = %w(c cont)
@@ -39,45 +39,15 @@ See also 'step', 'next', 'finish', and 'nexti' commands.
39
39
 
40
40
  ## FIXME: DRY this code, tbreak and break.
41
41
  unless args.size == 1
42
- describe, klass_name, which, name, line, ip =
43
- @proc.breakpoint_position(args[1..-1])
44
- unless describe
45
- errmsg "Can't parse temporary breakpoint location"
46
- return
47
- end
48
- if name.kind_of?(Rubinius::CompiledMethod)
49
- bp = @proc.set_breakpoint_method(describe, name, line, ip,
50
- {:temp=>true, :event =>'tbrkpt'})
51
- unless bp
52
- errmsg "Trouble setting temporary breakpoint"
53
- return
54
- end
42
+ cm, line, ip, condition, negate =
43
+ @proc.breakpoint_position(@proc.cmd_argstr, false)
44
+ if cm
45
+ opts={:event => 'tbrkpt', :temp => true}
46
+ bp = @proc.set_breakpoint_method(cm, line, ip, opts)
47
+ bp.set_temp!
55
48
  else
56
- return unless klass_name
57
- begin
58
- klass = @proc.debug_eval(klass_name, settings[:maxstring])
59
- rescue NameError
60
- errmsg "Unable to find class/module: #{klass_name}"
61
- return
62
- end
63
-
64
- begin
65
- if which == "#"
66
- method = klass.instance_method(name)
67
- else
68
- method = klass.method(name)
69
- end
70
- rescue NameError
71
- errmsg "Unable to find method '#{name}' in #{klass}"
72
- return
73
- end
74
- arg_str = args[1..-1].join(' ')
75
- bp = @proc.set_breakpoint_method(arg_str.strip, method, line, nil,
76
- {:temp=>true, :event =>'tbrkpt'})
77
- unless bp
78
- errmsg "Trouble setting temporary breakpoint"
79
- return
80
- end
49
+ errmsg "Trouble setting temporary breakpoint"
50
+ return
81
51
  end
82
52
  end
83
53
  @proc.continue('continue')
@@ -140,6 +140,8 @@ if __FILE__ == $0
140
140
  cmd.run([cmd.name, 'self.setup'])
141
141
  puts '=' * 40
142
142
  cmd.run([cmd.name, __LINE__.to_s])
143
+ require 'irb'
144
+ cmd.run([cmd.name, 'IRB.start'])
143
145
  end
144
146
  foo(cmd)
145
147
  end
@@ -18,17 +18,18 @@ may be used again easily. The name of the global variable is printed
18
18
  next to the inspect output of the value.
19
19
 
20
20
  If no string is given we run the string from the current source code
21
- about to be run. If the command ends ? (via an alias) and no string
22
- is given we will also strip off any leading 'if', 'while', 'elseif' or
23
- 'until' in the string.
21
+ about to be run. If the command ends ? (via an alias) and no string is
22
+ given we will also strip off any leading 'if', 'while', 'elseif',
23
+ 'return', 'case', 'unless', or 'until' in the string.
24
24
 
25
25
  #{NAME} 1+2 # 3
26
26
  #{NAME} @v
27
27
  #{NAME} # Run current source-code line
28
- #{NAME}? # but strips off leading 'if', 'while', 'elsif' or 'until'
28
+ #{NAME}? # but strips off leading 'if', 'while', ..
29
29
  # from command
30
30
 
31
- See also 'set autoeval'
31
+ See also 'set autoeval'. The command helps one predict future execution.
32
+ See 'set buffer trace' for showing what may have already been run.
32
33
  HELP
33
34
 
34
35
  ALIASES = %w(eval? ev? ev)
@@ -40,9 +41,20 @@ See also 'set autoeval'
40
41
  def run(args)
41
42
  if args.size == 1
42
43
  text = @proc.current_source_text
43
- text.gsub!(/^\s*(?:if|elsif|until|while)\s*/,'') if
44
- '?' == args[0][-1..-1]
45
- msg "eval: #{text}"
44
+ if '?' == args[0][-1..-1]
45
+ if text =~ /^\s*(?:if|elsif|unless)\s+/
46
+ text.gsub!(/^\s*(?:if|elsif|unless)\s+/,'')
47
+ text.gsub!(/\s+then\s*$/, '')
48
+ elsif text =~ /^\s*(?:until|while)\s+/
49
+ text.gsub!(/^\s*(?:until|while)\s+/,'')
50
+ text.gsub!(/\s+do\s*$/, '')
51
+ elsif text =~ /^\s*return\s+/
52
+ text.gsub!(/^\s*return\s+/,'')
53
+ elsif text =~ /^\s*case\s+/
54
+ text.gsub!(/^\s*case\s*/,'')
55
+ end
56
+ msg "eval: #{text}"
57
+ end
46
58
  else
47
59
  text = @proc.cmd_argstr
48
60
  end
@@ -46,8 +46,9 @@ See also "kill" and "set confirm".'
46
46
  end
47
47
  exitrc = (args.size > 1) ? exitrc = Integer(args[1]) rescue 0 : 0
48
48
 
49
- # FIXME: funnel to sort of more general finalize routine
50
- @proc.dbgr.intf[-1].close
49
+ # FIXME: Is this the best/most general way?
50
+ @proc.finalize
51
+ @proc.dbgr.intf[-1].finalize
51
52
 
52
53
  # No graceful way to stop threads...
53
54
  # A little harsh, but for now let's go with this.
File without changes
@@ -0,0 +1,48 @@
1
+ overall debugger command syntax
2
+
3
+ Command tokenization syntax is very simple-minded.
4
+
5
+ If a line starts with #, the command is ignored.
6
+ If a line starts with !, the line is eval'd.
7
+
8
+ If the command you want eval'd uses the Ruby ! initially, add that
9
+ after the first ! or start the line with a space.
10
+
11
+ Commands are split at whereever ;; appears. This process disregards
12
+ any quotes or other symbols that have meaning in Ruby. The strings
13
+ after the leading command string are put back on a command queue.
14
+
15
+ Within a single command, tokens are then white-space split. Again,
16
+ this process disregards quotes or symbols that have meaning in Ruby.
17
+ Some commands like 'eval', 'macro', and 'break' have access to the
18
+ untokenized string entered and make use of that rather than the
19
+ tokenized list.
20
+
21
+ The leading token is first looked up in the macro table. If it is in
22
+ the table, the expansion is replaces the current command and possibly
23
+ other commands pushed onto a command queue. Next, the leading token is
24
+ looked up in the debugger alias table and the name may be substituted
25
+ there. Finally, the leading token is looked up in the debugger alias
26
+ table. If a match is found, the command name and arguments are
27
+ dispatched to the command object that process the command.
28
+
29
+ If the command is not found and "auto eval" is set on, then the
30
+ command is eval'd in the context that the program is currently stopped
31
+ at. If "auto eval" is not set on, then we display an error message
32
+ that the entered string is "undefined".
33
+
34
+ If you want irb-like command-processing, it's possible to go into an
35
+ irb shell with the "irb" command. It is also possible to arrange going
36
+ into an irb shell every time you enter the debugger.
37
+
38
+ Examples:
39
+
40
+ # This line does nothing. It is a comment
41
+ s # by default, this is an alias for the "step" command
42
+ !s # shows the value of variable step.
43
+ !!s # Evaluates !s (or "not s"). The first ! is indicates evaluate.
44
+ info program;; list # Runs two commands "info program" and "list"
45
+ pr "hi ;;-)" # Syntax error since ;; splits the line and " is not closed.
46
+ !puts "hi ;;-)" # One way to do the above.
47
+
48
+ See also "alias", "irb", "set auto eval", and "set auto irb".