ruby-debug 0.9.3 → 0.10.0

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 (64) hide show
  1. data/AUTHORS +1 -0
  2. data/CHANGES +41 -0
  3. data/ChangeLog +0 -0
  4. data/README +27 -13
  5. data/Rakefile +220 -0
  6. data/bin/rdebug +116 -42
  7. data/cli/ruby-debug.rb +33 -3
  8. data/cli/ruby-debug/command.rb +49 -12
  9. data/cli/ruby-debug/commands/breakpoints.rb +47 -64
  10. data/cli/ruby-debug/commands/control.rb +41 -13
  11. data/cli/ruby-debug/commands/display.rb +35 -18
  12. data/cli/ruby-debug/commands/enable.rb +159 -0
  13. data/cli/ruby-debug/commands/eval.rb +78 -4
  14. data/cli/ruby-debug/commands/frame.rb +67 -42
  15. data/cli/ruby-debug/commands/help.rb +21 -17
  16. data/cli/ruby-debug/commands/info.rb +210 -0
  17. data/cli/ruby-debug/commands/irb.rb +9 -1
  18. data/cli/ruby-debug/commands/list.rb +11 -8
  19. data/cli/ruby-debug/commands/method.rb +12 -23
  20. data/cli/ruby-debug/commands/script.rb +14 -9
  21. data/cli/ruby-debug/commands/settings.rb +174 -39
  22. data/cli/ruby-debug/commands/show.rb +193 -0
  23. data/cli/ruby-debug/commands/stepping.rb +15 -10
  24. data/cli/ruby-debug/commands/threads.rb +55 -56
  25. data/cli/ruby-debug/commands/variables.rb +27 -27
  26. data/cli/ruby-debug/helper.rb +134 -0
  27. data/cli/ruby-debug/interface.rb +46 -15
  28. data/cli/ruby-debug/processor.rb +156 -25
  29. data/doc/rdebug.1 +236 -0
  30. data/runner.sh +7 -0
  31. data/test/breakpoints.cmd +43 -0
  32. data/test/breakpoints.right +94 -0
  33. data/test/display.cmd +18 -0
  34. data/test/display.right +37 -0
  35. data/test/frame.cmd +21 -0
  36. data/test/frame.right +45 -0
  37. data/test/gcd.rb +18 -0
  38. data/test/help.cmd +12 -0
  39. data/test/help.right +4 -0
  40. data/test/helper.rb +87 -0
  41. data/test/info-var-bug.rb +45 -0
  42. data/test/info-var.cmd +23 -0
  43. data/test/info-var.right +47 -0
  44. data/test/info.cmd +12 -0
  45. data/test/info.right +35 -0
  46. data/test/quit.cmd +9 -0
  47. data/test/quit.right +22 -0
  48. data/test/setshow.cmd +44 -0
  49. data/test/setshow.right +73 -0
  50. data/test/stepping.cmd +17 -0
  51. data/test/stepping.right +40 -0
  52. data/test/tdebug.rb +196 -0
  53. data/test/test-breakpoints.rb +28 -0
  54. data/test/test-columnize.rb +46 -0
  55. data/test/test-display.rb +26 -0
  56. data/test/test-frame.rb +27 -0
  57. data/test/test-help.rb +44 -0
  58. data/test/test-info-var.rb +33 -0
  59. data/test/test-info.rb +28 -0
  60. data/test/test-quit.rb +28 -0
  61. data/test/test-ruby-debug-base.rb +76 -0
  62. data/test/test-setshow.rb +24 -0
  63. data/test/test-stepping.rb +26 -0
  64. metadata +63 -22
@@ -0,0 +1,193 @@
1
+ module Debugger
2
+ # Mix-in module to showing settings
3
+ module ShowFunctions # :nodoc:
4
+ def show_setting(setting_name)
5
+ case setting_name
6
+ when /^annotate$/
7
+ Debugger.annotate ||= 0
8
+ return ("Annotation level is #{Debugger.annotate}")
9
+ when /^args$/
10
+ if Command.settings[:argv] and Command.settings[:argv].size > 0
11
+ args = Command.settings[:argv][1..-1].join(' ')
12
+ else
13
+ args = ''
14
+ end
15
+ return "Argument list to give program being debugged when it is started is \"#{args}\"."
16
+ when /^autolist$/
17
+ on_off = Command.settings[:autolist] > 0
18
+ return "autolist is #{show_onoff(on_off)}."
19
+ when /^autoeval$/
20
+ on_off = Command.settings[:autoeval]
21
+ return "autoeval is #{show_onoff(on_off)}."
22
+ when /^autoreload$/
23
+ on_off = Command.settings[:reload_source_on_change]
24
+ return "autoreload is #{show_onoff(on_off)}."
25
+ when /^autoirb$/
26
+ on_off = Command.settings[:autoirb] > 0
27
+ return "autoirb is #{show_onoff(on_off)}."
28
+ when /^basename$/
29
+ on_off = Command.settings[:basename]
30
+ return "basename is #{show_onoff(on_off)}."
31
+ when /^callstyle$/
32
+ style = Command.settings[:callstyle]
33
+ return "Frame call-display style is #{style}."
34
+ when /^debuggertesting$/
35
+ on_off = Command.settings[:debuggertesting]
36
+ return "Currently testing the debugger is #{show_onoff(on_off)}."
37
+ when /^forcestep$/
38
+ on_off = self.class.settings[:force_stepping]
39
+ return "force-stepping is #{show_onoff(on_off)}."
40
+ when /^fullpath$/
41
+ on_off = Command.settings[:full_path]
42
+ return "Displaying frame's full file names is #{show_onoff(on_off)}."
43
+ when /^history(:?\s+(filename|save|size))?$/
44
+ args = @match[1].split
45
+ interface = @state.interface
46
+ if args[1]
47
+ show_save = show_size = show_filename = false
48
+ prefix = false
49
+ if args[1] == "save"
50
+ show_save = true
51
+ elsif args[1] == "size"
52
+ show_size = true
53
+ elsif args[1] == "filename"
54
+ show_filename = true
55
+ end
56
+ else
57
+ show_save = show_size = show_filename = true
58
+ prefix = true
59
+ end
60
+ s = []
61
+ if show_filename
62
+ msg = (prefix ? "filename: " : "") +
63
+ "The filename in which to record the command history is " +
64
+ "#{interface.histfile.inspect}"
65
+ s << msg
66
+ end
67
+ if show_save
68
+ msg = (prefix ? "save: " : "") +
69
+ "Saving of history save is #{show_onoff(interface.history_save)}."
70
+ s << msg
71
+ end
72
+ if show_size
73
+ msg = (prefix ? "size: " : "") +
74
+ "Debugger history size is #{interface.history_length}"
75
+ s << msg
76
+ end
77
+ return s.join("\n")
78
+ when /^keep-frame-bindings$/
79
+ on_off = Debugger.keep_frame_binding?
80
+ return "keep-frame-bindings is #{show_onoff(on_off)}."
81
+ when /^linetrace$/
82
+ on_off = Debugger.tracing
83
+ return "line tracing is #{show_onoff(on_off)}."
84
+ when /^linetrace\+$/
85
+ on_off = Command.settings[:tracing_plus]
86
+ if on_off
87
+ return "line tracing style is different consecutive lines."
88
+ else
89
+ return "line tracing style is every line."
90
+ end
91
+ when /^listsize$/
92
+ listlines = Command.settings[:listsize]
93
+ return "Number of source lines to list by default is #{listlines}."
94
+ when /^port$/
95
+ return "server port is #{Debugger::PORT}."
96
+ when /^post-mortem$/
97
+ on_off = Debugger.post_mortem
98
+ return "post-mortem handling is #{show_onoff(on_off)}."
99
+ when /^trace$/
100
+ on_off = Command.settings[:stack_trace_on_error]
101
+ return "Displaying stack trace is #{show_onoff(on_off)}."
102
+ when /^version$/
103
+ return "ruby-debug #{Debugger::VERSION}"
104
+ when /^width$/
105
+ return "width is #{self.class.settings[:width]}."
106
+ else
107
+ return "Unknown show subcommand #{setting_name}."
108
+ end
109
+ end
110
+ end
111
+
112
+ class ShowCommand < Command # :nodoc:
113
+
114
+ SubcmdStruct=Struct.new(:name, :min, :short_help) unless
115
+ defined?(SubcmdStruct)
116
+ Subcommands =
117
+ [
118
+ ['annotate', 2, "Show annotation level"],
119
+ ['args', 2,
120
+ "Show argument list to give program being debugged when it is started"],
121
+ ['autoeval', 4, "Show if unrecognized command are evaluated"],
122
+ ['autolist', 4, "Show if 'list' commands is run on breakpoints"],
123
+ ['autoirb', 4, "Show if IRB is invoked on debugger stops"],
124
+ ['autoreload', 4, "Show if source code is reloaded when changed"],
125
+ ['basename', 1, "Show if basename used in reporting files"],
126
+ ['callstyle', 2, "Show paramater style used showing call frames"],
127
+ ['forcestep', 1, "Show if sure 'next/step' forces move to a new line"],
128
+ ['fullpath', 2, "Show if full file names are displayed in frames"],
129
+ ['history', 2, "Generic command for showing command history parameters"],
130
+ ['keep-frame-bindings', 1, "Save frame binding on each call"],
131
+ ['linetrace', 3, "Show line execution tracing"],
132
+ ['linetrace+', 10,
133
+ "Show if consecutive lines should be different are shown in tracing"],
134
+ ['listsize', 3, "Show number of source lines to list by default"],
135
+ ['port', 1, "Show server port"],
136
+ ['trace', 1,
137
+ "Show if a stack trace is displayed when 'eval' raises exception"],
138
+ ['version', 1,
139
+ "Show what version of the debugger this is"],
140
+ ['width', 1,
141
+ "Show the number of characters the debugger thinks are in a line"],
142
+ ].map do |name, min, short_help|
143
+ SubcmdStruct.new(name, min, short_help)
144
+ end unless defined?(Subcommands)
145
+
146
+ self.control = true
147
+
148
+ def regexp
149
+ /^show (?: \s+ (.+) )?$/xi
150
+ end
151
+
152
+ def execute
153
+ if not @match[1]
154
+ print "\"show\" must be followed by the name of an show command:\n"
155
+ print "List of show subcommands:\n\n"
156
+ for subcmd in Subcommands do
157
+ print "show #{subcmd.name} -- #{subcmd.short_help}\n"
158
+ end
159
+ else
160
+ subcmd, arg = @match[1].split(/[ \t]+/)
161
+ subcmd.downcase!
162
+ for try_subcmd in Subcommands do
163
+ if (subcmd.size >= try_subcmd.min) and
164
+ (try_subcmd.name[0..subcmd.size-1] == subcmd)
165
+ print "%s\n" % show_setting(try_subcmd.name)
166
+ return
167
+ end
168
+ end
169
+ print "Unknown show command #{subcmd}\n"
170
+ end
171
+ end
172
+
173
+ class << self
174
+ def help_command
175
+ "show"
176
+ end
177
+
178
+ def help(cmd)
179
+ s = "
180
+ Generic command for showing things about the debugger.
181
+
182
+ --
183
+ List of show subcommands:
184
+ --
185
+ "
186
+ for subcmd in Subcommands do
187
+ s += "show #{subcmd.name} -- #{subcmd.short_help}\n"
188
+ end
189
+ return s
190
+ end
191
+ end
192
+ end
193
+ end
@@ -3,12 +3,13 @@ module Debugger
3
3
  self.need_context = true
4
4
 
5
5
  def regexp
6
- /^\s*n(?:ext)?([+-])?(?:\s+(\d+))?$/
6
+ /^\s*n(?:ext)?([+])?(?:\s+(.*))?$/
7
7
  end
8
8
 
9
9
  def execute
10
10
  force = @match[1] == '+' || (@match[1].nil? && Command.settings[:force_stepping])
11
- steps = @match[2] ? @match[2].to_i : 1
11
+ steps = get_int(@match[2], "Next", 1)
12
+ return unless steps
12
13
  @state.context.step_over steps, @state.frame_pos, force
13
14
  @state.proceed
14
15
  end
@@ -20,7 +21,7 @@ module Debugger
20
21
 
21
22
  def help(cmd)
22
23
  %{
23
- n[ext][+][ nnn]\tstep over once or nnn times,
24
+ n[ext][+]?[ nnn]\tstep over once or nnn times,
24
25
  \t\t'+' forces to move to another line
25
26
  }
26
27
  end
@@ -31,12 +32,13 @@ module Debugger
31
32
  self.need_context = true
32
33
 
33
34
  def regexp
34
- /^\s*s(?:tep)?([+-])?(?:\s+(\d+))?$/
35
+ /^\s*s(?:tep)?([+])?(?:\s+(.*))?$/
35
36
  end
36
37
 
37
38
  def execute
38
39
  force = @match[1] == '+' || (@match[1].nil? && Command.settings[:force_stepping])
39
- steps = @match[2] ? @match[2].to_i : 1
40
+ steps = get_int(@match[2], "Step", 1)
41
+ return unless steps
40
42
  @state.context.step(steps, force)
41
43
  @state.proceed
42
44
  end
@@ -48,7 +50,8 @@ module Debugger
48
50
 
49
51
  def help(cmd)
50
52
  %{
51
- s[tep][ nnn]\tstep (into methods) once or nnn times
53
+ s[tep][+]?[ nnn]\tstep (into methods) once or nnn times
54
+ \t\t'+' forces to move to another line
52
55
  }
53
56
  end
54
57
  end
@@ -86,25 +89,27 @@ module Debugger
86
89
 
87
90
  class ContinueCommand < Command # :nodoc:
88
91
  def regexp
89
- /^\s*c(?:ont)?(?:\s+(\d+))?$/
92
+ /^\s*c(?:ont(?:inue)?)?(?:\s+(.*))?$/
90
93
  end
91
94
 
92
95
  def execute
93
96
  if @match[1] && !@state.context.dead?
94
97
  file = File.expand_path(@state.file)
95
- @state.context.set_breakpoint(file, @match[1].to_i)
98
+ line = get_int(@match[1], "Continue", 0, nil, 0)
99
+ return unless line
100
+ @state.context.set_breakpoint(file, line)
96
101
  end
97
102
  @state.proceed
98
103
  end
99
104
 
100
105
  class << self
101
106
  def help_command
102
- 'cont'
107
+ 'continue'
103
108
  end
104
109
 
105
110
  def help(cmd)
106
111
  %{
107
- c[ont][ nnn]\trun until program ends or hits breakpoint or reaches line nnn
112
+ c[ont[inue]][ nnn]\trun until program ends or hits breakpoint or reaches line nnn
108
113
  }
109
114
  end
110
115
  end
@@ -12,11 +12,31 @@ module Debugger
12
12
  end
13
13
  print "\n"
14
14
  end
15
+
16
+ def parse_thread_num(subcmd, arg)
17
+ if '' == arg
18
+ print "'thread %s' needs a thread number\n" % subcmd
19
+ else
20
+ thread_num = get_int(arg, "thread #{subcmd}", 1)
21
+ return nil unless thread_num
22
+ c = get_context(thread_num)
23
+ case
24
+ when nil == c
25
+ print "No such thread.\n"
26
+ when @state.context == c
27
+ print "It's the current thread.\n"
28
+ when c.ignored?
29
+ print "Can't #{subcmd} to the debugger thread.\n"
30
+ else # Everything is okay
31
+ return c
32
+ end
33
+ end
34
+ return nil
35
+ end
15
36
  end
16
37
 
17
38
  class ThreadListCommand < Command # :nodoc:
18
39
  self.control = true
19
- include ThreadFunctions
20
40
 
21
41
  def regexp
22
42
  /^\s*th(?:read)?\s+l(?:ist)?\s*$/
@@ -41,29 +61,19 @@ module Debugger
41
61
  end
42
62
  end
43
63
 
44
- class ThreadSwitchCommand < Command # :nodoc:
64
+ class ThreadStopCommand < Command # :nodoc:
45
65
  self.control = true
46
66
  self.need_context = true
47
67
 
48
- include ThreadFunctions
49
-
50
68
  def regexp
51
- /^\s*th(?:read)?\s+(?:sw(?:itch)?\s+)?(\d+)\s*$/
69
+ /^\s*th(?:read)?\s+stop\s*(\S*)\s*$/
52
70
  end
53
71
 
54
72
  def execute
55
- c = get_context(@match[1].to_i)
56
- case
57
- when c == @state.context
58
- print "It's the current thread.\n"
59
- when c.ignored?
60
- print "Can't switch to the debugger thread.\n"
61
- else
62
- display_context(c)
63
- c.stop_next = 1
64
- c.thread.run
65
- @state.proceed
66
- end
73
+ c = parse_thread_num("stop", @match[1])
74
+ return unless c
75
+ c.suspend
76
+ display_context(c)
67
77
  end
68
78
 
69
79
  class << self
@@ -73,33 +83,29 @@ module Debugger
73
83
 
74
84
  def help(cmd)
75
85
  %{
76
- th[read] [sw[itch]] <nnn>\tswitch thread context to nnn
86
+ th[read] stop <nnn>\t\tstop thread nnn
77
87
  }
78
88
  end
79
89
  end
80
90
  end
81
91
 
82
- class ThreadStopCommand < Command # :nodoc:
92
+ class ThreadResumeCommand < Command # :nodoc:
83
93
  self.control = true
84
94
  self.need_context = true
85
95
 
86
- include ThreadFunctions
87
-
88
96
  def regexp
89
- /^\s*th(?:read)?\s+stop\s+(\d+)\s*$/
97
+ /^\s*th(?:read)?\s+resume\s*(\S*)\s*$/
90
98
  end
91
99
 
92
100
  def execute
93
- c = get_context(@match[1].to_i)
94
- case
95
- when c == @state.context
96
- print "It's the current thread.\n"
97
- when c.ignored?
98
- print "Can't stop the debugger thread.\n"
99
- else
100
- c.suspend
101
- display_context(c)
101
+ c = parse_thread_num("resume", @match[1])
102
+ return unless c
103
+ if !c.thread.stop?
104
+ print "Already running."
105
+ return
102
106
  end
107
+ c.resume
108
+ display_context(c)
103
109
  end
104
110
 
105
111
  class << self
@@ -109,23 +115,30 @@ module Debugger
109
115
 
110
116
  def help(cmd)
111
117
  %{
112
- th[read] stop <nnn>\t\tstop thread nnn
118
+ th[read] resume <nnn>\t\tresume thread nnn
113
119
  }
114
120
  end
115
121
  end
116
122
  end
117
123
 
118
- class ThreadCurrentCommand < Command # :nodoc:
124
+ # Thread switch Must come after "Thread resume" because "switch" is
125
+ # optional
126
+
127
+ class ThreadSwitchCommand < Command # :nodoc:
128
+ self.control = true
119
129
  self.need_context = true
120
130
 
121
- include ThreadFunctions
122
-
123
131
  def regexp
124
- /^\s*th(?:read)?\s+c(?:ur(?:rent)?)?\s*$/
132
+ /^\s*th(?:read)?\s*(?:sw(?:itch)?)?\s+(\S+)\s*$/
125
133
  end
126
134
 
127
135
  def execute
128
- display_context(@state.context)
136
+ c = parse_thread_num("switch", @match[1])
137
+ return unless c
138
+ display_context(c)
139
+ c.stop_next = 1
140
+ c.thread.run
141
+ @state.proceed
129
142
  end
130
143
 
131
144
  class << self
@@ -135,35 +148,21 @@ module Debugger
135
148
 
136
149
  def help(cmd)
137
150
  %{
138
- th[read] c[ur[rent]]\t\tshow current thread
151
+ th[read] [sw[itch]] <nnn>\tswitch thread context to nnn
139
152
  }
140
153
  end
141
154
  end
142
155
  end
143
156
 
144
- class ThreadResumeCommand < Command # :nodoc:
145
- self.control = true
157
+ class ThreadCurrentCommand < Command # :nodoc:
146
158
  self.need_context = true
147
159
 
148
- include ThreadFunctions
149
-
150
160
  def regexp
151
- /^\s*th(?:read)?\s+resume\s+(\d+)\s*$/
161
+ /^\s*th(?:read)?\s*(?:cur(?:rent)?)?\s*$/
152
162
  end
153
163
 
154
164
  def execute
155
- c = get_context(@match[1].to_i)
156
- case
157
- when c == @state.context
158
- print "It's the current thread.\n"
159
- when c.ignored?
160
- print "Can't resume the debugger thread.\n"
161
- when !c.thread.stop?
162
- print "Already running."
163
- else
164
- c.resume
165
- display_context(c)
166
- end
165
+ display_context(@state.context)
167
166
  end
168
167
 
169
168
  class << self
@@ -173,7 +172,7 @@ module Debugger
173
172
 
174
173
  def help(cmd)
175
174
  %{
176
- th[read] resume <nnn>\t\tresume thread nnn
175
+ th[read] [cur[rent]]\t\tshow current thread
177
176
  }
178
177
  end
179
178
  end