ruby-debug 0.9.3 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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