ruby-debug 0.10.0 → 0.10.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 (152) hide show
  1. data/CHANGES +94 -2
  2. data/ChangeLog +5225 -0
  3. data/README +30 -1
  4. data/Rakefile +55 -24
  5. data/bin/rdebug +249 -128
  6. data/cli/ruby-debug/command.rb +30 -3
  7. data/cli/ruby-debug/commands/breakpoints.rb +54 -24
  8. data/cli/ruby-debug/commands/catchpoint.rb +13 -12
  9. data/cli/ruby-debug/commands/condition.rb +49 -0
  10. data/cli/ruby-debug/commands/continue.rb +32 -0
  11. data/cli/ruby-debug/commands/control.rb +19 -43
  12. data/cli/ruby-debug/commands/disassemble.RB +38 -0
  13. data/cli/ruby-debug/commands/display.rb +1 -1
  14. data/cli/ruby-debug/commands/edit.rb +48 -0
  15. data/cli/ruby-debug/commands/enable.rb +78 -35
  16. data/cli/ruby-debug/commands/eval.rb +6 -5
  17. data/cli/ruby-debug/commands/finish.rb +42 -0
  18. data/cli/ruby-debug/commands/frame.rb +64 -33
  19. data/cli/ruby-debug/commands/help.rb +19 -15
  20. data/cli/ruby-debug/commands/info.rb +295 -36
  21. data/cli/ruby-debug/commands/irb.rb +3 -1
  22. data/cli/ruby-debug/commands/list.rb +27 -50
  23. data/cli/ruby-debug/commands/quit.rb +38 -0
  24. data/cli/ruby-debug/commands/reload.rb +40 -0
  25. data/cli/ruby-debug/commands/save.rb +80 -0
  26. data/cli/ruby-debug/commands/{settings.rb → set.rb} +50 -12
  27. data/cli/ruby-debug/commands/show.rb +83 -27
  28. data/cli/ruby-debug/commands/source.rb +36 -0
  29. data/cli/ruby-debug/commands/stepping.rb +36 -72
  30. data/cli/ruby-debug/commands/threads.rb +32 -23
  31. data/cli/ruby-debug/commands/variables.rb +34 -4
  32. data/cli/ruby-debug/helper.rb +10 -75
  33. data/cli/ruby-debug/interface.rb +72 -9
  34. data/cli/ruby-debug/processor.rb +203 -100
  35. data/doc/rdebug.1 +7 -2
  36. data/rdbg.rb +33 -0
  37. data/test/{test-ruby-debug-base.rb → base/base.rb} +27 -29
  38. data/test/base/binding.rb +31 -0
  39. data/test/base/catchpoint.rb +26 -0
  40. data/test/base/load.rb +40 -0
  41. data/test/data/annotate.cmd +29 -0
  42. data/test/data/annotate.right +137 -0
  43. data/test/data/break_bad.cmd +18 -0
  44. data/test/data/break_bad.right +28 -0
  45. data/test/data/breakpoints.cmd +38 -0
  46. data/test/data/breakpoints.right +98 -0
  47. data/test/data/condition.cmd +28 -0
  48. data/test/data/condition.right +65 -0
  49. data/test/data/ctrl.cmd +23 -0
  50. data/test/data/ctrl.right +69 -0
  51. data/test/{display.cmd → data/display.cmd} +7 -1
  52. data/test/{display.right → data/display.right} +13 -6
  53. data/test/data/dollar-0.right +2 -0
  54. data/test/data/dollar-0a.right +2 -0
  55. data/test/data/dollar-0b.right +2 -0
  56. data/test/data/edit.cmd +12 -0
  57. data/test/data/edit.right +19 -0
  58. data/test/{breakpoints.cmd → data/emacs_basic.cmd} +0 -0
  59. data/test/{breakpoints.right → data/emacs_basic.right} +24 -12
  60. data/test/data/enable.cmd +20 -0
  61. data/test/data/enable.right +36 -0
  62. data/test/data/finish.cmd +16 -0
  63. data/test/data/finish.right +43 -0
  64. data/test/{frame.cmd → data/frame.cmd} +2 -0
  65. data/test/{frame.right → data/frame.right} +8 -2
  66. data/test/{help.cmd → data/help.cmd} +8 -0
  67. data/test/data/help.right +21 -0
  68. data/test/data/history.right +7 -0
  69. data/test/data/info-thread.cmd +13 -0
  70. data/test/data/info-thread.right +37 -0
  71. data/test/data/info-var-bug2.cmd +5 -0
  72. data/test/data/info-var-bug2.right +10 -0
  73. data/test/{info-var.cmd → data/info-var.cmd} +3 -3
  74. data/test/{info-var.right → data/info-var.right} +20 -15
  75. data/test/{info.cmd → data/info.cmd} +10 -1
  76. data/test/data/info.right +65 -0
  77. data/test/data/linetrace.cmd +6 -0
  78. data/test/data/linetrace.right +32 -0
  79. data/test/data/linetracep.cmd +7 -0
  80. data/test/data/linetracep.right +25 -0
  81. data/test/data/list.cmd +19 -0
  82. data/test/data/list.right +127 -0
  83. data/test/data/noquit.right +1 -0
  84. data/test/data/output.cmd +6 -0
  85. data/test/data/output.right +41 -0
  86. data/test/data/post-mortem-next.cmd +8 -0
  87. data/test/data/post-mortem-next.right +14 -0
  88. data/test/data/post-mortem-osx.right +31 -0
  89. data/test/data/post-mortem.cmd +13 -0
  90. data/test/data/post-mortem.right +31 -0
  91. data/test/{quit.cmd → data/quit.cmd} +2 -5
  92. data/test/data/quit.right +9 -0
  93. data/test/data/raise.cmd +11 -0
  94. data/test/data/raise.right +26 -0
  95. data/test/{setshow.cmd → data/setshow.cmd} +0 -1
  96. data/test/{setshow.right → data/setshow.right} +0 -1
  97. data/test/data/source.cmd +5 -0
  98. data/test/data/source.right +15 -0
  99. data/test/{stepping.cmd → data/stepping.cmd} +6 -2
  100. data/test/{stepping.right → data/stepping.right} +13 -3
  101. data/test/data/test-init-cygwin.right +7 -0
  102. data/test/data/test-init-osx.right +4 -0
  103. data/test/data/test-init.right +5 -0
  104. data/test/data/trace.right +23 -0
  105. data/test/dollar-0.rb +5 -0
  106. data/test/except-bug2.rb +7 -0
  107. data/test/gcd-dbg-nox.rb +31 -0
  108. data/test/gcd-dbg.rb +30 -0
  109. data/test/helper.rb +44 -14
  110. data/test/info-var-bug.rb +2 -0
  111. data/test/info-var-bug2.rb +2 -0
  112. data/test/null.rb +1 -0
  113. data/test/output.rb +2 -0
  114. data/test/pm-base.rb +22 -0
  115. data/test/pm.rb +11 -0
  116. data/test/raise.rb +3 -0
  117. data/test/tdebug.rb +88 -40
  118. data/test/test-annotate.rb +25 -0
  119. data/test/test-break-bad.rb +25 -0
  120. data/test/test-breakpoints.rb +14 -17
  121. data/test/test-condition.rb +25 -0
  122. data/test/test-ctrl.rb +54 -0
  123. data/test/test-display.rb +15 -15
  124. data/test/test-dollar-0.rb +39 -0
  125. data/test/test-edit.rb +26 -0
  126. data/test/test-emacs-basic.rb +26 -0
  127. data/test/test-enable.rb +25 -0
  128. data/test/test-finish.rb +34 -0
  129. data/test/test-frame.rb +15 -16
  130. data/test/test-help.rb +34 -18
  131. data/test/test-hist.rb +68 -0
  132. data/test/test-info-thread.rb +32 -0
  133. data/test/test-info-var.rb +28 -14
  134. data/test/test-info.rb +15 -17
  135. data/test/test-init.rb +41 -0
  136. data/test/test-list.rb +25 -0
  137. data/test/test-output.rb +26 -0
  138. data/test/test-pm.rb +46 -0
  139. data/test/test-quit.rb +19 -17
  140. data/test/test-raise.rb +25 -0
  141. data/test/test-setshow.rb +14 -13
  142. data/test/test-source.rb +25 -0
  143. data/test/test-stepping.rb +14 -14
  144. data/test/test-trace.rb +63 -0
  145. data/test/thread1.rb +26 -0
  146. metadata +125 -31
  147. data/cli/ruby-debug/commands/script.rb +0 -64
  148. data/runner.sh +0 -7
  149. data/test/help.right +0 -4
  150. data/test/info.right +0 -35
  151. data/test/quit.right +0 -22
  152. data/test/test-columnize.rb +0 -46
@@ -0,0 +1,36 @@
1
+ module Debugger
2
+ # Implements debugger "source" command.
3
+ class SourceCommand < Command
4
+ self.allow_in_control = true
5
+
6
+ def regexp
7
+ /^\s* so(?:urce)? \s+ (.+) $/x
8
+ end
9
+
10
+ def execute
11
+ file = File.expand_path(@match[1]).strip
12
+ unless File.exist?(file)
13
+ errmsg "Command file '#{file}' is not found\n"
14
+ return
15
+ end
16
+ if @state and @state.interface
17
+ @state.interface.command_queue += File.open(file).readlines
18
+ else
19
+ Debugger.run_script(file, @state)
20
+ end
21
+ end
22
+
23
+ class << self
24
+ def help_command
25
+ 'source'
26
+ end
27
+
28
+ def help(cmd)
29
+ %{
30
+ source FILE\texecutes a file containing debugger commands
31
+ }
32
+ end
33
+ end
34
+ end
35
+
36
+ end
@@ -1,14 +1,31 @@
1
1
  module Debugger
2
- class NextCommand < Command # :nodoc:
3
- self.need_context = true
2
+ # Mix-in module to assist in command parsing.
3
+ module SteppingFunctions # :nodoc:
4
+ def parse_stepping_args(command_name, match)
5
+ if match[1].nil?
6
+ force = Command.settings[:force_stepping]
7
+ elsif match[1] == '+'
8
+ force = true
9
+ elsif match[1] == '-'
10
+ force = false
11
+ end
12
+ steps = get_int(match[2], command_name, 1)
13
+ return [steps, force]
14
+ end
15
+ end
16
+ # Implements debugger "next" command.
17
+ class NextCommand < Command
18
+ self.allow_in_post_mortem = false
19
+ self.need_context = true
4
20
 
5
21
  def regexp
6
- /^\s*n(?:ext)?([+])?(?:\s+(.*))?$/
22
+ /^\s* n(?:ext)?
23
+ ([+-])?(?:\s+(\S+))?
24
+ \s*$/x
7
25
  end
8
26
 
9
27
  def execute
10
- force = @match[1] == '+' || (@match[1].nil? && Command.settings[:force_stepping])
11
- steps = get_int(@match[2], "Next", 1)
28
+ steps, force = parse_stepping_args("Next", @match)
12
29
  return unless steps
13
30
  @state.context.step_over steps, @state.frame_pos, force
14
31
  @state.proceed
@@ -21,23 +38,27 @@ module Debugger
21
38
 
22
39
  def help(cmd)
23
40
  %{
24
- n[ext][+]?[ nnn]\tstep over once or nnn times,
25
- \t\t'+' forces to move to another line
41
+ n[ext][+-]?[ nnn]\tstep over once or nnn times,
42
+ \t\t'+' forces to move to another line.
43
+ \t\t'-' is the opposite of '+' and disables the force_stepping setting.
26
44
  }
27
45
  end
28
46
  end
29
47
  end
30
48
 
31
- class StepCommand < Command # :nodoc:
32
- self.need_context = true
49
+ # Implements debugger "step" command.
50
+ class StepCommand < Command
51
+ self.allow_in_post_mortem = false
52
+ self.need_context = true
33
53
 
34
54
  def regexp
35
- /^\s*s(?:tep)?([+])?(?:\s+(.*))?$/
55
+ /^\s* s(?:tep)?
56
+ ([+-])?(?:\s+(\S+))?
57
+ \s*$/x
36
58
  end
37
59
 
38
60
  def execute
39
- force = @match[1] == '+' || (@match[1].nil? && Command.settings[:force_stepping])
40
- steps = get_int(@match[2], "Step", 1)
61
+ steps, force = parse_stepping_args("Step", @match)
41
62
  return unless steps
42
63
  @state.context.step(steps, force)
43
64
  @state.proceed
@@ -50,66 +71,9 @@ module Debugger
50
71
 
51
72
  def help(cmd)
52
73
  %{
53
- s[tep][+]?[ nnn]\tstep (into methods) once or nnn times
54
- \t\t'+' forces to move to another line
55
- }
56
- end
57
- end
58
- end
59
-
60
- class FinishCommand < Command # :nodoc:
61
- self.need_context = true
62
-
63
- def regexp
64
- /^\s*fin(?:ish)?$/
65
- end
66
-
67
- def execute
68
- if @state.frame_pos == @state.context.stack_size - 1
69
- print "\"finish\" not meaningful in the outermost frame.\n"
70
- else
71
- @state.context.stop_frame = @state.frame_pos
72
- @state.frame_pos = 0
73
- @state.proceed
74
- end
75
- end
76
-
77
- class << self
78
- def help_command
79
- 'finish'
80
- end
81
-
82
- def help(cmd)
83
- %{
84
- fin[ish]\treturn to outer frame
85
- }
86
- end
87
- end
88
- end
89
-
90
- class ContinueCommand < Command # :nodoc:
91
- def regexp
92
- /^\s*c(?:ont(?:inue)?)?(?:\s+(.*))?$/
93
- end
94
-
95
- def execute
96
- if @match[1] && !@state.context.dead?
97
- file = File.expand_path(@state.file)
98
- line = get_int(@match[1], "Continue", 0, nil, 0)
99
- return unless line
100
- @state.context.set_breakpoint(file, line)
101
- end
102
- @state.proceed
103
- end
104
-
105
- class << self
106
- def help_command
107
- 'continue'
108
- end
109
-
110
- def help(cmd)
111
- %{
112
- c[ont[inue]][ nnn]\trun until program ends or hits breakpoint or reaches line nnn
74
+ s[tep][+-]?[ nnn]\tstep (into methods) once or nnn times
75
+ \t\t'+' forces to move to another line.
76
+ \t\t'-' is the opposite of '+' and disables the force_stepping setting.
113
77
  }
114
78
  end
115
79
  end
@@ -1,13 +1,13 @@
1
1
  module Debugger
2
2
  module ThreadFunctions # :nodoc:
3
- def display_context(c)
3
+ def display_context(c, show_top_frame=true)
4
4
  c_flag = c.thread == Thread.current ? '+' : ' '
5
5
  c_flag = '$' if c.suspended?
6
6
  d_flag = c.ignored? ? '!' : ' '
7
7
  print "%s%s", c_flag, d_flag
8
8
  print "%d ", c.thnum
9
9
  print "%s\t", c.thread.inspect
10
- if c.stack_size > 0
10
+ if c.stack_size > 0 and show_top_frame
11
11
  print "%s:%d", c.frame_file(0), c.frame_line(0)
12
12
  end
13
13
  print "\n"
@@ -15,28 +15,34 @@ module Debugger
15
15
 
16
16
  def parse_thread_num(subcmd, arg)
17
17
  if '' == arg
18
- print "'thread %s' needs a thread number\n" % subcmd
18
+ errmsg "'%s' needs a thread number\n" % subcmd
19
+ nil
19
20
  else
20
21
  thread_num = get_int(arg, "thread #{subcmd}", 1)
21
22
  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
23
+ get_context(thread_num)
24
+ end
25
+ end
26
+
27
+ def parse_thread_num_for_cmd(subcmd, arg)
28
+ c = parse_thread_num(subcmd, arg)
29
+ return nil unless c
30
+ case
31
+ when nil == c
32
+ errmsg "No such thread.\n"
33
+ when @state.context == c
34
+ errmsg "It's the current thread.\n"
35
+ when c.ignored?
36
+ errmsg "Can't #{subcmd} to the debugger thread #{arg}.\n"
37
+ else # Everything is okay
38
+ return c
33
39
  end
34
40
  return nil
35
41
  end
36
42
  end
37
43
 
38
44
  class ThreadListCommand < Command # :nodoc:
39
- self.control = true
45
+ self.allow_in_control = true
40
46
 
41
47
  def regexp
42
48
  /^\s*th(?:read)?\s+l(?:ist)?\s*$/
@@ -62,15 +68,16 @@ module Debugger
62
68
  end
63
69
 
64
70
  class ThreadStopCommand < Command # :nodoc:
65
- self.control = true
66
- self.need_context = true
71
+ self.allow_in_control = true
72
+ self.allow_in_post_mortem = false
73
+ self.need_context = true
67
74
 
68
75
  def regexp
69
76
  /^\s*th(?:read)?\s+stop\s*(\S*)\s*$/
70
77
  end
71
78
 
72
79
  def execute
73
- c = parse_thread_num("stop", @match[1])
80
+ c = parse_thread_num_for_cmd("thread stop", @match[1])
74
81
  return unless c
75
82
  c.suspend
76
83
  display_context(c)
@@ -90,7 +97,8 @@ module Debugger
90
97
  end
91
98
 
92
99
  class ThreadResumeCommand < Command # :nodoc:
93
- self.control = true
100
+ self.allow_in_post_mortem = false
101
+ self.allow_in_control = true
94
102
  self.need_context = true
95
103
 
96
104
  def regexp
@@ -98,7 +106,7 @@ module Debugger
98
106
  end
99
107
 
100
108
  def execute
101
- c = parse_thread_num("resume", @match[1])
109
+ c = parse_thread_num_for_cmd("thread resume", @match[1])
102
110
  return unless c
103
111
  if !c.thread.stop?
104
112
  print "Already running."
@@ -125,15 +133,16 @@ module Debugger
125
133
  # optional
126
134
 
127
135
  class ThreadSwitchCommand < Command # :nodoc:
128
- self.control = true
129
- self.need_context = true
136
+ self.allow_in_control = true
137
+ self.allow_in_post_mortem = false
138
+ self.need_context = true
130
139
 
131
140
  def regexp
132
141
  /^\s*th(?:read)?\s*(?:sw(?:itch)?)?\s+(\S+)\s*$/
133
142
  end
134
143
 
135
144
  def execute
136
- c = parse_thread_num("switch", @match[1])
145
+ c = parse_thread_num_for_cmd("thread switch", @match[1])
137
146
  return unless c
138
147
  display_context(c)
139
148
  c.stop_next = 1
@@ -18,18 +18,46 @@ module Debugger
18
18
  print "%s = %s\n", v, s
19
19
  end
20
20
  end
21
+ def var_class_self
22
+ obj = debug_eval('self')
23
+ var_list(obj.class.class_variables, get_binding)
24
+ end
25
+ end
26
+
27
+ class VarClassVarCommand < Command # :nodoc:
28
+ def regexp
29
+ /^\s*v(?:ar)?\s+cl(?:ass)?/
30
+ end
31
+
32
+ def execute
33
+ unless @state.context
34
+ print "can't get class variables here.\n"
35
+ return
36
+ end
37
+ var_class_self
38
+ end
39
+
40
+ class << self
41
+ def help_command
42
+ 'var'
43
+ end
44
+
45
+ def help(cmd)
46
+ %{
47
+ v[ar] cl[ass] \t\t\tshow class variables of self
48
+ }
49
+ end
50
+ end
21
51
  end
22
52
 
23
53
  class VarConstantCommand < Command # :nodoc:
24
54
  def regexp
25
- /^\s*v(?:ar)?\s+c(?:onst(?:ant)?)?\s+/
55
+ /^\s*v(?:ar)?\s+co(?:nst(?:ant)?)?\s+/
26
56
  end
27
57
 
28
58
  def execute
29
59
  obj = debug_eval(@match.post_match)
30
- unless obj.kind_of? Module
31
- print "Should be Class/Module: %s\n", @match.post_match
32
- else
60
+ if obj.kind_of? Module
33
61
  constants = debug_eval("#{@match.post_match}.constants")
34
62
  constants.sort!
35
63
  for c in constants
@@ -37,6 +65,8 @@ module Debugger
37
65
  value = obj.const_get(c) rescue "ERROR: #{$!}"
38
66
  print " %s => %p\n", c, value
39
67
  end
68
+ else
69
+ print "Should be Class/Module: %s\n", @match.post_match
40
70
  end
41
71
  end
42
72
 
@@ -1,81 +1,8 @@
1
1
  module Debugger
2
2
 
3
- module ColumnizeFunctions
4
- # Display a list of strings as a compact set of columns.
5
- #
6
- # Each column is only as wide as necessary.
7
- # Columns are separated by two spaces (one was not legible enough).
8
- # Adapted from the routine of the same name in cmd.py
9
- def columnize(list, displaywidth=80)
10
- if not list.is_a?(Array)
11
- return "Expecting an Array, got #{list.class}\n"
12
- end
13
- if list.size == 0
14
- return "<empty>\n"
15
- end
16
- nonstrings = []
17
- for str in list do
18
- nonstrings << str unless str.is_a?(String)
19
- end
20
- if nonstrings.size > 0
21
- return "Nonstrings: %s\n" % nonstrings.map {|non| non.to_s}.join(', ')
22
- end
23
- if 1 == list.size
24
- return "#{list[0]}\n"
25
- end
26
- # Try every row count from 1 upwards
27
- nrows = ncols = 0
28
- colwidths = []
29
- 1.upto(list.size) do
30
- colwidths = []
31
- nrows += 1
32
- ncols = (list.size + nrows-1) / nrows
33
- totwidth = -2
34
- # Debugger.debugger if nrows > 1
35
- 0.upto(ncols-1) do |col|
36
- colwidth = 0
37
- 0.upto(nrows-1) do |row|
38
- i = row + nrows*col
39
- if i >= list.size
40
- break
41
- end
42
- colwidth = [colwidth, list[i].size].max
43
- end
44
- colwidths << colwidth
45
- totwidth += colwidth + 2
46
- if totwidth > displaywidth
47
- break
48
- end
49
- end
50
- if totwidth <= displaywidth
51
- break
52
- end
53
- end
54
- s = ''
55
- 0.upto(nrows-1) do |row|
56
- texts = []
57
- 0.upto(ncols-1) do |col|
58
- i = row + nrows*col
59
- if i >= list.size
60
- x = ""
61
- else
62
- x = list[i]
63
- end
64
- texts << x
65
- end
66
- while texts and texts[-1] == ''
67
- texts = texts[0..-2]
68
- end
69
- 0.upto(texts.size-1) do |col|
70
- texts[col] = texts[col].ljust(colwidths[col])
71
- end
72
- s += "%s\n" % texts.join(" ")
73
- end
74
- return s
75
- end
76
- end
77
-
78
3
  module ParseFunctions
4
+ Position_regexp = '(?:(\d+)|(.+?)[:.#]([^.:\s]+))'
5
+
79
6
  # Parse 'str' of command 'cmd' as an integer between
80
7
  # min and max. If either min or max is nil, that
81
8
  # value has no bound.
@@ -130,5 +57,13 @@ module Debugger
130
57
  end
131
58
  return bool ? 'on' : 'off'
132
59
  end
60
+
61
+ # Return true if code is syntactically correct for Ruby.
62
+ def syntax_valid?(code)
63
+ eval("BEGIN {return true}\n#{code}", nil, "", 0)
64
+ rescue Exception
65
+ false
66
+ end
67
+
133
68
  end
134
69
  end