trepanning 1.93.35 → 2.15.33

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 (134) hide show
  1. checksums.yaml +7 -0
  2. data/ChangeLog +491 -55
  3. data/LICENSE +1 -1
  4. data/NEWS +18 -14
  5. data/README.md +5 -22
  6. data/Rakefile +22 -1
  7. data/app/breakpoint.rb +5 -3
  8. data/app/core.rb +147 -179
  9. data/app/default.rb +47 -46
  10. data/app/file.rb +6 -7
  11. data/app/frame.rb +183 -176
  12. data/app/markdown.rb +2 -9
  13. data/app/options.rb +1 -1
  14. data/app/run.rb +71 -37
  15. data/interface/script.rb +8 -8
  16. data/io.rb +19 -20
  17. data/lib/trepanning.rb +292 -297
  18. data/processor.rb +332 -344
  19. data/processor/breakpoint.rb +98 -96
  20. data/processor/command/base/submgr.rb +9 -9
  21. data/processor/command/break.rb +40 -38
  22. data/processor/command/continue.rb +15 -10
  23. data/processor/command/debug.rb +6 -25
  24. data/processor/command/delete.rb +21 -12
  25. data/processor/command/directory.rb +15 -13
  26. data/processor/command/disable.rb +12 -9
  27. data/processor/command/disassemble.rb +80 -74
  28. data/processor/command/display.rb +15 -12
  29. data/processor/command/down.rb +8 -3
  30. data/processor/command/edit.rb +37 -23
  31. data/processor/command/enable.rb +11 -8
  32. data/processor/command/eval.rb +24 -22
  33. data/processor/command/finish.rb +50 -48
  34. data/processor/command/help.rb +1 -1
  35. data/processor/command/info_subcmd/breakpoints.rb +7 -7
  36. data/processor/command/info_subcmd/files.rb +195 -196
  37. data/processor/command/info_subcmd/frame.rb +7 -4
  38. data/processor/command/info_subcmd/locals.rb +29 -12
  39. data/processor/command/info_subcmd/program.rb +48 -39
  40. data/processor/command/info_subcmd/registers_subcmd/ep.rb +46 -0
  41. data/processor/command/info_subcmd/registers_subcmd/helper.rb +32 -35
  42. data/processor/command/info_subcmd/registers_subcmd/sp.rb +29 -23
  43. data/processor/command/info_subcmd/return.rb +28 -10
  44. data/processor/command/info_subcmd/variables_subcmd/class.rb +3 -3
  45. data/processor/command/info_subcmd/variables_subcmd/constants.rb +77 -0
  46. data/processor/command/info_subcmd/variables_subcmd/globals.rb +7 -7
  47. data/processor/command/info_subcmd/variables_subcmd/instance.rb +68 -22
  48. data/processor/command/info_subcmd/variables_subcmd/locals.rb +148 -67
  49. data/processor/command/list.rb +14 -8
  50. data/processor/command/macro.rb +1 -1
  51. data/processor/command/next.rb +1 -0
  52. data/processor/command/set_subcmd/auto.rb +3 -3
  53. data/processor/command/set_subcmd/different.rb +30 -29
  54. data/processor/command/set_subcmd/events.rb +74 -48
  55. data/processor/command/set_subcmd/max_subcmd/list.rb +12 -5
  56. data/processor/command/set_subcmd/max_subcmd/width.rb +28 -19
  57. data/processor/command/set_subcmd/register.rb +37 -0
  58. data/processor/command/set_subcmd/register_subcmd/pc.rb +67 -0
  59. data/processor/command/set_subcmd/register_subcmd/sp.rb +75 -0
  60. data/processor/command/set_subcmd/reload.rb +12 -10
  61. data/processor/command/set_subcmd/return.rb +68 -44
  62. data/processor/command/shell.rb +3 -2
  63. data/processor/command/show_subcmd/different.rb +17 -14
  64. data/processor/command/show_subcmd/events.rb +25 -25
  65. data/processor/default.rb +1 -1
  66. data/processor/eval.rb +14 -15
  67. data/processor/frame.rb +43 -36
  68. data/processor/help.rb +5 -5
  69. data/processor/hook.rb +26 -29
  70. data/processor/location.rb +54 -51
  71. data/processor/mock.rb +4 -3
  72. data/processor/running.rb +113 -103
  73. data/processor/validate.rb +401 -373
  74. data/test/data/debug.cmd +8 -0
  75. data/test/data/debug.right +13 -0
  76. data/test/data/debugger-stop.right +6 -4
  77. data/test/data/fname-with-blank.cmd +1 -1
  78. data/test/data/fname-with-blank.right +5 -0
  79. data/test/data/pc.cmd +8 -0
  80. data/test/data/pc.right +10 -0
  81. data/test/data/quit.right +3 -1
  82. data/test/data/trace.cmd +2 -2
  83. data/test/data/trace.right +41 -20
  84. data/test/example/assign.rb +6 -0
  85. data/test/functional/fn_helper.rb +11 -17
  86. data/test/functional/test-break-long.rb +15 -16
  87. data/test/functional/test-break.rb +6 -8
  88. data/test/functional/test-condition.rb +8 -10
  89. data/test/functional/test-debugger-call-bug.rb +21 -22
  90. data/test/functional/test-delete.rb +57 -59
  91. data/test/functional/test-eval.rb +101 -103
  92. data/test/functional/test-finish.rb +24 -33
  93. data/test/functional/test-immediate-step-bug.rb +6 -10
  94. data/test/functional/test-next.rb +64 -65
  95. data/test/functional/test-raise.rb +63 -64
  96. data/test/functional/test-recursive-bt.rb +81 -76
  97. data/test/functional/test-remap.rb +6 -7
  98. data/test/functional/test-return.rb +44 -38
  99. data/test/functional/test-step.rb +55 -53
  100. data/test/functional/test-stepbug.rb +6 -9
  101. data/test/functional/test-watchg.rb +40 -39
  102. data/test/integration/test-debug.rb +12 -0
  103. data/test/integration/test-debugger-stop.rb +7 -7
  104. data/test/integration/test-pc.rb +24 -0
  105. data/test/integration/test-trace.rb +1 -1
  106. data/test/unit/cmd-helper.rb +0 -1
  107. data/test/unit/test-app-brkpt.rb +21 -21
  108. data/test/unit/test-app-brkptmgr.rb +7 -8
  109. data/test/unit/test-app-display.rb +3 -4
  110. data/test/unit/test-app-frame.rb +4 -5
  111. data/test/unit/test-base-subsubcmd.rb +2 -2
  112. data/test/unit/test-cmd-break.rb +6 -6
  113. data/test/unit/test-cmd-endisable.rb +7 -6
  114. data/test/unit/test-cmd-parse_list_cmd.rb +24 -24
  115. data/test/unit/test-io-tcpserver.rb +39 -35
  116. data/test/unit/test-proc-default.rb +23 -22
  117. data/test/unit/test-proc-eval.rb +1 -2
  118. data/test/unit/test-proc-frame.rb +8 -9
  119. data/test/unit/test-proc-list.rb +1 -1
  120. data/test/unit/test-proc-location.rb +2 -2
  121. data/test/unit/test-proc-main.rb +10 -10
  122. data/test/unit/test-proc-validate.rb +11 -13
  123. data/test/unit/test-subcmd-help.rb +1 -2
  124. data/trepanning.gemspec +8 -13
  125. metadata +44 -95
  126. data/COPYING +0 -57
  127. data/data/custom_require.rb +0 -44
  128. data/data/perldb.bindings +0 -17
  129. data/data/prelude.rb +0 -38
  130. data/processor/command/info_subcmd/variables_subcmd/constant.rb +0 -41
  131. data/processor/command/raise.rb +0 -48
  132. data/processor/command/set_subcmd/pc.rb +0 -62
  133. data/processor/command/set_subcmd/sp.rb +0 -67
  134. data/processor/eventbuf.rb +0 -133
@@ -14,11 +14,6 @@ module Redcarpet
14
14
  attr_accessor :width
15
15
  attr_accessor :try_ansi
16
16
 
17
- def strip_term_sequence(text)
18
- # to be completed...
19
- text
20
- end
21
-
22
17
  # reflow text so lines are not
23
18
  # longer than @width. prefix
24
19
  # is used only after the first line
@@ -29,7 +24,7 @@ module Redcarpet
29
24
  line = ''
30
25
  width = @width - prefix.size
31
26
  text.split.each do |word|
32
- word_size = strip_term_sequence(word).size
27
+ word_size = Term::ANSIColor::uncolor(word).size
33
28
  if (line_len + word_size) >= width
34
29
  lines << line
35
30
  line = prefix + word + ' '
@@ -58,7 +53,7 @@ module Redcarpet
58
53
 
59
54
  def codespan(text)
60
55
  if ansi?
61
- Term::ANSIColor.underline + text + Term::ANSIColor.reset
56
+ Term::ANSIColor.underline + text + Term::ANSIColor.reset + "\n"
62
57
  else
63
58
  "'" + text + "'"
64
59
  end
@@ -162,8 +157,6 @@ if __FILE__ == $0
162
157
  # HI
163
158
  This is a paragraph
164
159
 
165
- A `b`, `c`, d
166
-
167
160
  **This** is another *paragraph*.
168
161
  EOF
169
162
  [[80, true],
@@ -8,7 +8,7 @@ require 'optparse'
8
8
  class Trepan
9
9
  require_relative 'default'
10
10
 
11
- VERSION = '1.93.35'
11
+ VERSION = '2.15.33'
12
12
  PROGRAM = 'trepan'
13
13
 
14
14
  def self.show_version
data/app/run.rb CHANGED
@@ -1,9 +1,32 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010-2013 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010-2013, 2015 Rocky Bernstein <rockyb@rubyforge.net>
3
3
  require 'rbconfig'
4
4
  module Trepanning
5
5
 
6
- module_function # All functions below are easily publically accessible
6
+ class Termination < RuntimeError
7
+ end
8
+
9
+ module_function # All functions below are easily publically accessible
10
+
11
+ def run_program(dbgr, program_to_debug)
12
+ RubyVM::Frame::get.trace_off = false
13
+ RubyVM::Frame::get.trace_off1 = true
14
+ dbgr.core.processor.hidelevels[Thread.current] =
15
+ RubyVM::Frame.stack_size
16
+ dbgr.trace_point.enable
17
+
18
+ # FIXME: the magic skip count 4 below is to skip over
19
+ # the following calls triggered by Kernel::load
20
+ # c_call - IO#set_encoding(1)
21
+ # c_return - IO#set_encoding -> *debugged program*
22
+ # call - IO#set_encoding(1)
23
+ # c_return - IO#set_encoding -> *debugged program*
24
+ # This is not very robust. Figure out how to
25
+ # address this.
26
+ dbgr.core.step_count = 4
27
+ Kernel::load program_to_debug
28
+ end
29
+
7
30
 
8
31
  # Given a Ruby interpreter and program we are to debug, debug it.
9
32
  # The caller must ensure that ARGV is set up to remove any debugger
@@ -11,50 +34,61 @@ module Trepanning
11
34
  # see. FIXME: Should we make ARGV an explicit parameter?
12
35
  def debug_program(dbgr, program_to_debug)
13
36
 
14
- # Make sure Ruby script syntax checks okay.
15
- # Otherwise we get a load message that looks like trepanning has
16
- # a problem.
17
- output = ruby_syntax_errors(program_to_debug)
18
- if output
19
- puts output
20
- exit $?.exitstatus
21
- end
37
+ # Make sure Ruby script syntax checks okay.
38
+ # Otherwise we get a load message that looks like trepanning has
39
+ # a problem.
40
+ output = ruby_syntax_errors(program_to_debug)
41
+ if output
42
+ puts output
43
+ exit $?.exitstatus
44
+ end
22
45
 
23
- dbgr.trace_filter << self.method(:debug_program)
24
- dbgr.trace_filter << Kernel.method(:load)
46
+ # dbgr.trace_filter << self.method(:debug_program)
47
+ # dbgr.trace_filter << Kernel.method(:load)
48
+ dbgr.trace_filter << 'debug_program'
49
+ dbgr.trace_filter << 'load'
25
50
 
26
- old_dollar_0 = $0
51
+ old_dollar_0 = $0
27
52
 
28
- # Without the dance below to set $0, setting it to a signifcantly
29
- # longer value will truncate it in some OS's. See
30
- # http://www.ruby-forum.com/topic/187083
31
- $progname = program_to_debug
32
- alias $0 $progname
33
- dollar_0_tracker = lambda {|val| $program_name = val}
34
- trace_var(:$0, dollar_0_tracker)
53
+ # Without the dance below to set $0, setting it to a signifcantly
54
+ # longer value will truncate it in some OS's. See
55
+ # http://www.ruby-forum.com/topic/187083
56
+ $progname = program_to_debug
57
+ alias $0 $progname
58
+ dollar_0_tracker = lambda {|val| $program_name = val}
59
+ trace_var(:$0, dollar_0_tracker)
35
60
 
36
- dbgr.debugger(:hide_stack=>true) do
37
- dbgr.core.processor.hidelevels[Thread.current] =
38
- RubyVM::Frame.current.stack_size + 1
39
61
  begin
40
- Kernel::load program_to_debug
62
+ dbgr.start(false)
63
+ frame = RubyVM::Frame.get
64
+ while frame do
65
+ frame.trace_off = true
66
+ frame = frame.prev
67
+ end
68
+ run_program(dbgr, program_to_debug)
69
+ raise Termination
70
+ rescue Termination
71
+ if dbgr.settings[:cmdloop_on_exit]
72
+ dbgr.stop
73
+ puts "Program terminated, type q to quit"
74
+ dbgr.core.processor.process_commands(nil, 0)
75
+ end
41
76
  rescue Interrupt
42
77
  end
43
- end
44
78
 
45
- # The dance we have to undo to restore $0 and undo the mess created
46
- # above.
47
- $0 = old_dollar_0
48
- untrace_var(:$0, dollar_0_tracker)
79
+ # The dance we have to undo to restore $0 and undo the mess created
80
+ # above.
81
+ $0 = old_dollar_0
82
+ untrace_var(:$0, dollar_0_tracker)
49
83
  rescue
50
- if dbgr.settings[:post_mortem]
51
- frame = RubyVM::Frame.current.prev(0)
52
- dbgr.core.step_count = 0 # Make event processor stop
53
- dbgr.core.processor.settings[:debugstack] = 0 # Make event processor stop
54
- dbgr.core.event_processor('post-mortem', frame, $!)
55
- else
84
+ if dbgr.settings[:post_mortem]
85
+ frame = RubyVM::Frame.get
86
+ dbgr.core.step_count = 0 # Make event processor stop
87
+ dbgr.core.processor.settings[:debugstack] = 0 # Make event processor stop
88
+ dbgr.core.event_processor('post-mortem', frame, $!)
89
+ else
56
90
  raise
57
- end
91
+ end
58
92
  end
59
93
 
60
94
  # Do a shell-like path lookup for prog_script and return the results.
@@ -97,7 +131,7 @@ if __FILE__ == $0
97
131
  puts whence_file('irb')
98
132
  puts whence_file('probably-does-not-exist')
99
133
  puts RbConfig.ruby
100
- puts "#{__FILE__} is syntactically correct" unless
134
+ puts "#{__FILE__} is syntactically correct" unless
101
135
  ruby_syntax_errors(__FILE__)
102
136
  readme = File.join(File.dirname(__FILE__), '..', 'README.textile')
103
137
  puts "#{readme} is not syntactically correct" if
@@ -16,7 +16,7 @@ class Trepan::ScriptInterface < Trepan::Interface
16
16
  :confirm_val => false,
17
17
  :verbose => false
18
18
  } unless defined?(DEFAULT_OPTS)
19
-
19
+
20
20
  def initialize(script_name, out=nil, opts={})
21
21
 
22
22
  @opts = DEFAULT_OPTS.merge(opts)
@@ -24,7 +24,7 @@ class Trepan::ScriptInterface < Trepan::Interface
24
24
  at_exit { finalize }
25
25
  @script_name = script_name
26
26
  @input_lineno = 0
27
- @input = opts[:input] ||
27
+ @input = opts[:input] ||
28
28
  Trepan::UserInput.open(script_name, :line_edit => false)
29
29
  @buffer_output = []
30
30
  unless @opts[:verbose] or out
@@ -35,7 +35,7 @@ class Trepan::ScriptInterface < Trepan::Interface
35
35
 
36
36
  # Closes input only.
37
37
  def close
38
- @input.close
38
+ # @input.close unless @input.closed?
39
39
  end
40
40
 
41
41
  # Called when a dangerous action is about to be done, to make
@@ -48,7 +48,7 @@ class Trepan::ScriptInterface < Trepan::Interface
48
48
  end
49
49
 
50
50
  # Common routine for reporting debugger error messages.
51
- #
51
+ #
52
52
  def errmsg(msg, prefix="*** ")
53
53
  # self.verbose shows lines so we don't have to duplicate info
54
54
  # here. Perhaps there should be a 'terse' mode to never show
@@ -67,8 +67,8 @@ class Trepan::ScriptInterface < Trepan::Interface
67
67
  end
68
68
 
69
69
  def interactive? ; false end
70
-
71
- # Script interface to read a command. `prompt' is a parameter for
70
+
71
+ # Script interface to read a command. `prompt' is a parameter for
72
72
  # compatibilty and is ignored.
73
73
  def read_command(prompt='')
74
74
  @input_lineno += 1
@@ -81,12 +81,12 @@ class Trepan::ScriptInterface < Trepan::Interface
81
81
  return line
82
82
  end
83
83
 
84
- # Script interface to read a line. `prompt' is a parameter for
84
+ # Script interface to read a line. `prompt' is a parameter for
85
85
  # compatibilty and is ignored.
86
86
  #
87
87
  # Could decide make this look for interactive input?
88
88
  def readline(prompt='')
89
- begin
89
+ begin
90
90
  return input.readline().chomp
91
91
  rescue EOFError
92
92
  @eof = true
data/io.rb CHANGED
@@ -2,11 +2,11 @@
2
2
  # classes to support communication to and from the debugger. This
3
3
  # communcation might be to/from another process or another computer.
4
4
  # And reading may be from a debugger command script.
5
- #
5
+ #
6
6
  # For example, we'd like to support Sockets, and serial lines and file
7
7
  # reading, as well a readline-type input. Encryption and Authentication
8
8
  # methods might decorate some of the communication channels.
9
- #
9
+ #
10
10
  # Some ideas originiated as part of Matt Fleming's 2006 Google Summer of
11
11
  # Code project.
12
12
 
@@ -14,7 +14,7 @@ class Trepan
14
14
 
15
15
  NotImplementedMessage = 'This method must be overriden in a subclass' unless
16
16
  defined?(NotImplementedMessage)
17
-
17
+
18
18
  class InputBase
19
19
  attr_reader :input
20
20
  attr_reader :line_edit
@@ -30,10 +30,10 @@ class Trepan
30
30
  end
31
31
 
32
32
  def close
33
- @input.close unless @input.closed?
33
+ @input.close unless @input.closed?
34
34
  end
35
35
 
36
- def eof?
36
+ def eof?
37
37
  begin
38
38
  @input.eof?
39
39
  rescue IOError
@@ -41,7 +41,7 @@ class Trepan
41
41
  end
42
42
  end
43
43
 
44
- # Read a line of input. EOFError will be raised on EOF.
44
+ # Read a line of input. EOFError will be raised on EOF.
45
45
  #
46
46
  # Note that we don't support prompting first. Instead, arrange
47
47
  # to call Trepan::Output.write() first with the prompt. If
@@ -69,7 +69,7 @@ class Trepan
69
69
  @eof = true
70
70
  end
71
71
 
72
- def eof?
72
+ def eof?
73
73
  @eof
74
74
  end
75
75
 
@@ -77,7 +77,7 @@ class Trepan
77
77
  @output.flush
78
78
  end
79
79
 
80
- # Use this to set where to write to. output can be a
80
+ # Use this to set where to write to. output can be a
81
81
  # file object or a string. This code raises IOError on error.
82
82
  def write(*args)
83
83
  @output.print(*args)
@@ -95,17 +95,17 @@ class Trepan
95
95
  # handled by the same channel, e.g. a socket or tty.
96
96
  #
97
97
  class InOutBase
98
-
98
+
99
99
  def initialize(inout, opts={})
100
100
  @opts = DEFAULT_OPTS.merge(opts)
101
101
  @inout = inout
102
102
  end
103
-
103
+
104
104
  def close
105
105
  @inout.close() if @inout
106
106
  end
107
-
108
- def eof?
107
+
108
+ def eof?
109
109
  begin
110
110
  @input.eof?
111
111
  rescue IOError
@@ -116,9 +116,9 @@ class Trepan
116
116
  def flush
117
117
  @inout.flush
118
118
  end
119
-
120
- # Read a line of input. EOFError will be raised on EOF.
121
- #
119
+
120
+ # Read a line of input. EOFError will be raised on EOF.
121
+ #
122
122
  # Note that we don't support prompting first. Instead, arrange to
123
123
  # call DebuggerOutput.write() first with the prompt. If `use_raw'
124
124
  # is set raw_input() will be used in that is supported by the
@@ -128,15 +128,15 @@ class Trepan
128
128
  @input.readline
129
129
  end
130
130
 
131
- # Use this to set where to write to. output can be a
131
+ # Use this to set where to write to. output can be a
132
132
  # file object or a string. This code raises IOError on error.
133
- #
134
- # Use this to set where to write to. output can be a
133
+ #
134
+ # Use this to set where to write to. output can be a
135
135
  # file object or a string. This code raises IOError on error.
136
136
  def write(*args)
137
137
  @inout.write(*args)
138
138
  end
139
-
139
+
140
140
  # used to write to a debugger that is connected to this
141
141
  # server; `str' written will have a newline added to it
142
142
  def writeline( msg)
@@ -145,4 +145,3 @@ class Trepan
145
145
  end
146
146
 
147
147
  end
148
-
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- coding: utf-8 -*-
3
- # Copyright (C) 2010-2012 Rocky Bernstein <rockyb@rubyforge.net>
4
- require 'trace' # Trace filtering
5
- require 'thread_frame' # Stack frame introspection and more.
3
+ # Copyright (C) 2010-2012, 2015 Rocky Bernstein <rockyb@rubyforge.net>
4
+ require 'set'
6
5
  require_relative '../app/complete' # command completion
7
6
  require_relative '../app/core' # core event-handling mechanism
8
7
  require_relative '../app/default' # default debugger settings
@@ -11,13 +10,13 @@ require_relative '../interface/script' # --command interface (includes I/O)
11
10
  require_relative '../interface/client' # client interface (remote debugging)
12
11
  require_relative '../interface/server' # server interface (remote debugging)
13
12
 
14
- # SCRIPT_ISEQS__ is like SCRIPT_LINES__ in a patched Ruby 1.9. Setting
15
- # this variable to a hash causes instruction sequences to be added in
16
- # this has under their "filename" as a key. More accurately though,
17
- # the "filename" is instruction sequence name that was given as in the
18
- # "filename" parameter when the instruction sequence was
19
- # generated. Each value is an array of instruction sequences that
20
- # share that name.
13
+ # SCRIPT_ISEQS__ is like SCRIPT_LINES__ in a patched Ruby
14
+ # 1.9/2.1. Setting this variable to a hash causes instruction
15
+ # sequences to be added in this has under their "filename" as a
16
+ # key. More accurately though, the "filename" is instruction sequence
17
+ # name that was given as in the "filename" parameter when the
18
+ # instruction sequence was generated. Each value is an array of
19
+ # instruction sequences that share that name.
21
20
  SCRIPT_ISEQS__ = {} unless
22
21
  defined?(SCRIPT_ISEQS__) && SCRIPT_ISEQS__.is_a?(Hash)
23
22
  ISEQS__ = {} unless
@@ -25,318 +24,314 @@ ISEQS__ = {} unless
25
24
 
26
25
  class Trepan
27
26
 
28
- attr_reader :completion_proc # GNU Readline completion proc
29
- attr_accessor :core # access to Trepan::Core instance
30
- attr_accessor :intf # Array. The way the outside world
31
- # interfaces with us. An array, so that
32
- # interfaces can be stacked.
33
- attr_accessor :restart_argv # How to restart us, empty or nil.
34
- # Note: restart_argv is typically C's
35
- # **argv, not Ruby's ARGV. So
36
- # restart_argv[0] is $0.
37
- attr_reader :settings # Hash[:symbol] of things you can configure
38
- attr_accessor :trace_filter # Procs/Methods we ignore.
39
-
40
- def initialize(settings={})
41
-
42
- # FIXME: Tracing through intialization code is slow. Need to figure
43
- # out better ways to do this.
44
- th = Thread.current
45
- th.exec_event_tracing = true
46
-
47
- @settings = Trepan::DEFAULT_SETTINGS.merge(settings)
48
- @input = @settings[:input] || STDIN
49
- @output = @settings[:output] || STDOUT
50
-
51
- @completion_proc = method(:completion_method)
52
-
53
- @intf =
54
- if @settings[:server]
55
- @completion_proc = nil
56
- opts = Trepan::ServerInterface::DEFAULT_INIT_CONNECTION_OPTS.dup
57
- opts[:port] = @settings[:port] if @settings[:port]
58
- opts[:host] = @settings[:host] if @settings[:host]
27
+ attr_reader :completion_proc # GNU Readline completion proc
28
+ attr_accessor :core # access to Trepan::Core instance
29
+ attr_accessor :intf # Array. The way the outside world
30
+ # interfaces with us. An array, so that
31
+ # interfaces can be stacked.
32
+ attr_accessor :restart_argv # How to restart us, empty or nil.
33
+ # Note: restart_argv is typically C's
34
+ # **argv, not Ruby's ARGV. So
35
+ # restart_argv[0] is $0.
36
+ attr_reader :settings # Hash[:symbol] of things you can configure
37
+ attr_accessor :trace_filter # Procs/Methods we ignore.
38
+ attr_accessor :trace_point # Trace point object
39
+
40
+ def initialize(settings={})
41
+ @trace_point = nil
42
+ @trace_filter = Set.new()
43
+ @settings = Trepan::DEFAULT_SETTINGS.merge(settings)
44
+ @input = @settings[:input] || STDIN
45
+ @output = @settings[:output] || STDOUT
46
+
47
+ @completion_proc = method(:completion_method)
48
+
49
+ @intf =
50
+ if @settings[:server]
51
+ @completion_proc = nil
52
+ opts = Trepan::ServerInterface::DEFAULT_INIT_CONNECTION_OPTS.dup
53
+ opts[:port] = @settings[:port] if @settings[:port]
54
+ opts[:host] = @settings[:host] if @settings[:host]
59
55
  opts[:readline] = false
60
- puts("starting debugger in out-of-process mode port at " +
61
- "#{opts[:host]}:#{opts[:port]}")
62
- [Trepan::ServerInterface.new(nil, nil, opts)]
63
- elsif @settings[:client]
64
- opts = Trepan::ClientInterface::DEFAULT_INIT_CONNECTION_OPTS.dup
65
- opts[:port] = @settings[:port] if @settings[:port]
66
- opts[:host] = @settings[:host] if @settings[:host]
67
- opts[:complete] = @completion_proc
68
- user_opts = @settings[:user_opts] || {}
69
- [Trepan::ClientInterface.new(nil, nil, nil, user_opts, opts)]
70
- else
71
- opts = {:complete => @completion_proc,
56
+ puts("starting debugger in out-of-process mode port at " +
57
+ "#{opts[:host]}:#{opts[:port]}")
58
+ [Trepan::ServerInterface.new(nil, nil, opts)]
59
+ elsif @settings[:client]
60
+ opts = Trepan::ClientInterface::DEFAULT_INIT_CONNECTION_OPTS.dup
61
+ opts[:port] = @settings[:port] if @settings[:port]
62
+ opts[:host] = @settings[:host] if @settings[:host]
63
+ opts[:complete] = @completion_proc
64
+ user_opts = @settings[:user_opts] || {}
65
+ [Trepan::ClientInterface.new(nil, nil, nil, user_opts, opts)]
66
+ else
67
+ opts = {:complete => @completion_proc,
72
68
  :readline => @settings[:readline]}
73
- [Trepan::UserInterface.new(@input, @output, opts)]
74
- end
69
+ [Trepan::UserInterface.new(@input, @output, opts)]
70
+ end
75
71
 
76
- process_cmdfile_setting(@settings)
72
+ process_cmdfile_setting(@settings)
77
73
 
78
- # FIXME: The below option settings is a big crock.
79
- @settings[:core_opts][:cmdproc_opts] ||= {}
80
- @settings[:core_opts][:cmdproc_opts][:highlight] ||= settings[:highlight]
81
- @settings[:core_opts][:cmdproc_opts][:traceprint] = settings[:traceprint]
82
- @settings[:core_opts][:cmdproc_opts][:basename] = settings[:basename]
74
+ # FIXME: The below option settings is a big crock.
75
+ @settings[:core_opts][:cmdproc_opts] ||= {}
76
+ @settings[:core_opts][:cmdproc_opts][:basename] = settings[:basename]
77
+ @settings[:core_opts][:cmdproc_opts][:highlight] ||= settings[:highlight]
78
+ @settings[:core_opts][:cmdproc_opts][:traceprint] = settings[:traceprint]
83
79
 
84
- @core = Core.new(self, @settings[:core_opts])
80
+ if settings[:traceprint]
81
+ @settings[:cmdloop_on_exit] = false
82
+ end
85
83
 
86
- if @settings[:initial_dir]
87
- Dir.chdir(@settings[:initial_dir])
88
- else
89
- @settings[:initial_dir] = Dir.pwd
90
- end
91
- @initial_dir = @settings[:initial_dir]
92
- @restart_argv = @settings[:restart_argv]
93
-
94
- unless @settings[:client]
95
- @trace_filter = Trace::Filter.new
96
- %w(debugger start stop).each do |m|
97
- @trace_filter << self.method(m.to_sym)
98
- end
99
- %w(debugger event_processor trace_var_processor).each do
100
- |m|
101
- @trace_filter << @core.method(m)
102
- end
103
- @trace_filter << @trace_filter.method(:add_trace_func)
104
- @trace_filter << @trace_filter.method(:remove_trace_func)
105
- @trace_filter << Kernel.method(:add_trace_func)
106
- end
84
+ @core = Core.new(self, @settings[:core_opts])
85
+
86
+ if @settings[:initial_dir]
87
+ Dir.chdir(@settings[:initial_dir])
88
+ else
89
+ @settings[:initial_dir] = Dir.pwd
90
+ end
91
+ @initial_dir = @settings[:initial_dir]
92
+ @restart_argv = @settings[:restart_argv]
93
+
94
+ unless @settings[:client]
95
+ %w(debugger stop).each do |m|
96
+ @trace_filter << self.method(m.to_sym)
97
+ end
98
+ %w(debugger event_processor trace_var_processor).each do
99
+ |m|
100
+ # FIXME
101
+ # @trace_filter << @core.method(m)
102
+ @trace_filter << m
103
+ end
104
+ end
105
+
106
+ # Run user debugger command startup files.
107
+ add_startup_files unless @settings[:nx]
107
108
 
108
- # Run user debugger command startup files.
109
- add_startup_files unless @settings[:nx]
110
109
 
111
- at_exit do
112
- clear_trace_func
113
- @intf[-1].close
110
+ at_exit do
111
+ RubyVM::Frame::get.trace_off = true
112
+ stop
113
+ @intf[-1].close
114
+ end
114
115
  end
115
- th.exec_event_tracing = false
116
- end
117
-
118
- # The method is called when we want to do debugger command completion
119
- # such as called from GNU Readline with <TAB>.
120
- def completion_method(last_token, leading=Readline.line_buffer)
121
- completion = @core.processor.complete(leading, last_token)
122
- if 1 == completion.size
123
- completion_token = completion[0]
124
- if last_token.end_with?(' ')
125
- if last_token.rstrip == completion_token
126
- # There is nothing more to complete
127
- []
116
+
117
+ # The method is called when we want to do debugger command completion
118
+ # such as called from GNU Readline with <TAB>.
119
+ def completion_method(last_token, leading=Readline.line_buffer)
120
+ completion = @core.processor.complete(leading, last_token)
121
+ if 1 == completion.size
122
+ completion_token = completion[0]
123
+ if last_token.end_with?(' ')
124
+ if last_token.rstrip == completion_token
125
+ # There is nothing more to complete
126
+ []
127
+ else
128
+ []
129
+ end
130
+ else
131
+ [completion_token]
132
+ end
133
+ else
134
+ # We have multiple completions. Get the last token so that will
135
+ # be presented as a list of completions.
136
+ completion
137
+ end
138
+ end
139
+
140
+ # To call from inside a Ruby program, there is one-time setup that
141
+ # needs to be done first:
142
+ # require 'trepanning'
143
+ # mydbg = Trepan.new()
144
+ # which will tell the debugger how to "restart" the program.
145
+ #
146
+ # If you want a synchronous stop in your program call to the
147
+ # debugger at the point of the call, set opts[:immediate]
148
+ # true. Example:
149
+ #
150
+ # ... work, work, work
151
+ # mydbg.debugger(:immediate=>true) # enter debugger here
152
+ # ... work, work, work
153
+ #
154
+ # However to enter the debugger on the next event after the
155
+ # debugger() call:
156
+ #
157
+ # ... work, work, work
158
+ # mydbg.debugger # Don't stop here...
159
+ # work # but stop here.
160
+ #
161
+ # And finally, if you want to debug just a block:
162
+ # mydbg.debugger {
163
+ # ... code you want to debug.
164
+ # }
165
+ #
166
+ # Some options
167
+
168
+ # :immediate - boolean. If true, immediate stop rather than wait
169
+ # for an event
170
+ #
171
+ # :hide_stack - boolean. If true, omit stack frames before the
172
+ # debugger call
173
+ #
174
+ # :debugme - boolean. Allow tracing into this routine. You
175
+ # generally won't want this. It slows things
176
+ # down horribly.
177
+
178
+ def debugger(opts={}, &block)
179
+ # FIXME: one option we may want to pass is the initial trace
180
+ # filter.
181
+ if opts[:hide_stack]
182
+ @core.processor.hidelevels[Thread.current] =
183
+ RubyVM::Frame.get.stack_size
184
+ end
185
+ # unless defined?(PROG_UNRESOLVED_SCRIPT)
186
+ # # We may later do more sophisticated things...
187
+ # Trepan.const_set('PROG_UNRESOLVED_SCRIPT', RubyVM::OS_ARGV.index($0) ? $0 : nil)
188
+ # end
189
+ th = Thread.current
190
+ if block
191
+ @trace_point = TracePoint.new() do |tp|
192
+ @core.event_processor_tp(tp)
193
+ end
194
+ RubyVM::Frame::get.trace_off1 = true
195
+ @trace_point.enable
196
+ yield block
197
+ RubyVM::Frame::get.trace_off = true
198
+ @trace_point.disable
199
+ @trace_point = nil
128
200
  else
129
- []
201
+ @trace_point = TracePoint.new() do |tp|
202
+ @core.event_processor_tp(tp)
203
+ end
204
+ RubyVM::Frame::get.trace_off1 = true
205
+ @trace_point.enable
130
206
  end
131
- else
132
- [completion_token]
133
- end
134
- else
135
- # We have multiple completions. Get the last token so that will
136
- # be presented as a list of completions.
137
- completion
138
207
  end
139
- end
140
-
141
- # To call from inside a Ruby program, there is one-time setup that
142
- # needs to be done first:
143
- # require 'trepanning'
144
- # mydbg = Trepan.new()
145
- # which will tell the debugger how to "restart" the program.
146
- #
147
- # If you want a synchronous stop in your program call to the
148
- # debugger at the point of the call, set opts[:immediate]
149
- # true. Example:
150
- #
151
- # ... work, work, work
152
- # mydbg.debugger(:immediate=>true) # enter debugger here
153
- # ... work, work, work
154
- #
155
- # However to enter the debugger on the next event after the
156
- # debugger() call:
157
- #
158
- # ... work, work, work
159
- # mydbg.debugger # Don't stop here...
160
- # work # but stop here.
161
- #
162
- # And finally, if you want to debug just a block:
163
- # mydbg.debugger {
164
- # ... code you want to debug.
165
- # }
166
- #
167
- # Some options
168
-
169
- # :immediate - boolean. If true, immediate stop rather than wait
170
- # for an event
171
- #
172
- # :hide_stack - boolean. If true, omit stack frames before the
173
- # debugger call
174
- #
175
- # :debugme - boolean. Allow tracing into this routine. You
176
- # generally won't want this. It slows things
177
- # down horribly.
178
-
179
- def debugger(opts={}, &block)
180
- # FIXME: one option we may want to pass is the initial trace filter.
181
- if opts[:hide_stack]
182
- @core.processor.hidelevels[Thread.current] =
183
- RubyVM::Frame.current.stack_size
208
+
209
+ # Set core's trace-event processor to run
210
+ def start(enable = false)
211
+ @trace_point = TracePoint.new() do |tp|
212
+ @core.event_processor_tp(tp)
213
+ end
214
+ RubyVM::Frame::get.trace_off1 = true
215
+ @trace_point.enable if enable
184
216
  end
185
- # unless defined?(PROG_UNRESOLVED_SCRIPT)
186
- # # We may later do more sophisticated things...
187
- # Trepan.const_set('PROG_UNRESOLVED_SCRIPT', RubyVM::OS_ARGV.index($0) ? $0 : nil)
188
- # end
189
- th = Thread.current
190
- if block
191
- start
192
- ret = block.call
193
- stop
194
- return ret
195
- elsif opts[:immediate]
196
- # Stop immediately after this method returns. But if opts[:debugme]
197
- # is set, we can stop in this method.
198
- RubyVM::Frame::current.trace_off = true unless opts[:debugme]
199
- @trace_filter.set_trace_func(@core.event_proc)
200
- Trace.event_masks[0] |= @core.step_events
201
- @core.debugger(1)
202
- else
203
- RubyVM::Frame::current.trace_off = true unless opts[:debugme]
204
-
205
- @trace_filter.set_trace_func(@core.event_proc)
206
- Trace.event_masks[0] |= @core.step_events
207
-
208
- # Set to stop on the next event after this returns.
209
- @core.step_count = opts[:step_count] || 0
217
+
218
+ def stop
219
+ RubyVM::Frame::get.trace_off = true
220
+ @trace_point.disable if @trace_point and
221
+ @trace_point.respond_to?(:disable)
210
222
  end
211
- end
212
-
213
- # Set core's trace-event processor to run
214
- def start
215
- @trace_filter.add_trace_func(@core.event_proc)
216
- end
217
-
218
- # Remove all of our trace events
219
- def stop(opts={})
220
- # FIXME: should do something in the middle when
221
- # we have the ability to remove *our* specific hook
222
- # @trace_filter.set_trace_func(nil)
223
- # @trace_filter.remove_trace_func
224
- clear_trace_func
225
- end
226
-
227
- def add_command_file(cmdfile, stderr=$stderr)
228
- unless File.readable?(cmdfile)
229
- if File.exists?(cmdfile)
230
- stderr.puts "Command file '#{cmdfile}' is not readable."
231
- return
232
- else
233
- stderr.puts "Command file '#{cmdfile}' does not exist."
234
- return
235
- end
223
+
224
+ def add_command_file(cmdfile, opts={}, stderr=$stderr)
225
+ unless File.readable?(cmdfile)
226
+ if File.exists?(cmdfile)
227
+ stderr.puts "Command file '#{cmdfile}' is not readable."
228
+ return
229
+ else
230
+ stderr.puts "Command file '#{cmdfile}' does not exist."
231
+ return
232
+ end
233
+ end
234
+ @intf << Trepan::ScriptInterface.new(cmdfile, opts[:out])
236
235
  end
237
- @intf << Trepan::ScriptInterface.new(cmdfile)
238
- end
239
-
240
- def add_startup_files()
241
- seen = {}
242
- cwd_initfile = File.join('.', Trepan::CMD_INITFILE_BASE)
243
- [cwd_initfile, Trepan::CMD_INITFILE].each do |initfile|
244
- full_initfile_path = File.expand_path(initfile)
245
- next if seen[full_initfile_path]
246
- add_command_file(full_initfile_path) if File.readable?(full_initfile_path)
247
- seen[full_initfile_path] = true
236
+
237
+ def add_startup_files()
238
+ seen = {}
239
+ cwd_initfile = File.join('.', Trepan::CMD_INITFILE_BASE)
240
+ [cwd_initfile, Trepan::CMD_INITFILE].each do |initfile|
241
+ full_initfile_path = File.expand_path(initfile)
242
+ next if seen[full_initfile_path]
243
+ add_command_file(full_initfile_path) if File.readable?(full_initfile_path)
244
+ seen[full_initfile_path] = true
245
+ end
248
246
  end
249
- end
250
247
 
251
- def process_cmdfile_setting(settings)
252
- settings[:cmdfiles].each do |item|
253
- cmdfile, opts =
254
- if item.kind_of?(Array)
255
- item
256
- else
257
- [item, {}]
248
+ def process_cmdfile_setting(settings)
249
+ settings[:cmdfiles].each do |item|
250
+ cmdfile, opts =
251
+ if item.kind_of?(Array)
252
+ item
253
+ else
254
+ [item, {:out => @output}]
255
+ end
256
+ add_command_file(cmdfile, opts)
257
+ end if settings.member?(:cmdfiles)
258
+ end
259
+
260
+ # As a simplification for creating a debugger object, and then
261
+ # calling using the object to invoke the debugger, we allow this
262
+ # two-step process in one step. That is, instead of
263
+ #
264
+ # require 'trepanning'
265
+ # mydbg = Trepan.new()
266
+ # ...
267
+ # mydbg.debugger
268
+
269
+ # You can run:
270
+ # require 'trepanning'
271
+ # ...
272
+ # Trepan.debug
273
+ #
274
+ # See debugger for options that can be passed. By default :hide_stack is
275
+ # set.
276
+ #
277
+ # Likewise for mydbg.debugger{ ... }
278
+
279
+ def self.debug(opts={}, &block)
280
+ opts = {:hide_stack => false}.merge(opts)
281
+ unless defined?($trepanning) && $trepanning.is_a?(Trepan)
282
+ $trepanning = Trepan.new(opts)
258
283
  end
259
- add_command_file(cmdfile, opts)
260
- end if settings.member?(:cmdfiles)
261
- end
262
-
263
- # As a simplification for creating a debugger object, and then
264
- # calling using the object to invoke the debugger, we allow this
265
- # two-step process in one step. That is, instead of
266
- #
267
- # require 'trepanning'
268
- # mydbg = Trepan.new()
269
- # ...
270
- # mydbg.debugger
271
-
272
- # You can run:
273
- # require 'trepanning'
274
- # ...
275
- # Trepan.debug
276
- #
277
- # See debugger for options that can be passed. By default :hide_stack is
278
- # set.
279
- #
280
- # Likewise for mydbg.debugger{ ... }
281
-
282
- def self.debug(opts={}, &block)
283
- opts = {:hide_stack => false}.merge(opts)
284
- unless defined?($trepanning) && $trepanning.is_a?(Trepan)
285
- $trepanning = Trepan.new(opts)
284
+ $trepanning.debugger(opts, &block)
285
+ end
286
+
287
+ def self.debug_str(string, opts = DEFAULT_DEBUG_STR_SETTINGS)
288
+ $trepanning = Trepan.new(opts) unless
289
+ $trepanning && $trepanning.is_a?(Trepan)
290
+ $trepanning.core.processor.settings[:different] = false
291
+ # Perhaps we should do a remap file to string right here?
292
+ $trepanning.debugger(opts) { eval(string) }
286
293
  end
287
- tf = $trepanning.trace_filter
288
- tf << self.method(:debugger) unless tf.member? self.method(:debugger)
289
- $trepanning.debugger(opts, &block)
290
- end
291
-
292
- def self.debug_str(string, opts = DEFAULT_DEBUG_STR_SETTINGS)
293
- $trepanning = Trepan.new(opts) unless
294
- $trepanning && $trepanning.is_a?(Trepan)
295
- $trepanning.core.processor.settings[:different] = false
296
- # Perhaps we should do a remap file to string right here?
297
- $trepanning.debugger(opts) { eval(string) }
298
- end
299
294
  end
300
295
 
301
296
  module Kernel
302
- # Same as Trepan.debug.
303
- # FIXME figure out a way to remove duplication.
304
- def debugger(opts={}, &block)
305
- opts = {:hide_stack => false}.merge(opts)
306
- unless defined?($trepanning) && $trepanning.is_a?(Trepan)
307
- $trepanning = Trepan.new(opts)
297
+ # Same as Trepan.debug.
298
+ # FIXME figure out a way to remove duplication.
299
+ def debugger(opts={}, &block)
300
+ opts = {:hide_stack => false}.merge(opts)
301
+ unless defined?($trepanning) && $trepanning.is_a?(Trepan)
302
+ $trepanning = Trepan.new(opts)
303
+ end
304
+ tf = $trepanning.trace_filter
305
+ tf << self.method(:debugger) unless tf.member? self.method(:debugger)
306
+ $trepanning.debugger(opts)
308
307
  end
309
- tf = $trepanning.trace_filter
310
- tf << self.method(:debugger) unless tf.member? self.method(:debugger)
311
- $trepanning.debugger(opts)
312
- end
313
308
  end
314
309
 
315
310
  if __FILE__ == $0
316
- def square(x) # :nodoc
317
- x * x
318
- end
319
- puts 'block debugging...'
320
- # It is imagined that there are all sorts of command-line options here.
321
- # (I have a good imagination.)
322
- Trepan.debug {
323
- a = 2
324
- b = square(a)
325
- p "square of #{a} is #{b}"
326
- }
327
-
328
- puts 'immediate debugging...'
329
- $trepanning.debugger(:immediate => true)
330
- puts 'line after immediate'
331
- a = 3
332
- square(a)
333
-
334
- class MyClass
335
- def initialize(x)
336
- @x = x
311
+ def square(x) # :nodoc
312
+ x * x
313
+ end
314
+ puts 'block debugging...'
315
+ # It is imagined that there are all sorts of command-line options here.
316
+ # (I have a good imagination.)
317
+ Trepan.debug {
318
+ a = 2
319
+ b = square(a)
320
+ p "square of #{a} is #{b}"
321
+ }
322
+
323
+ puts 'immediate debugging (not)...'
324
+ $trepanning.debugger # (:immediate => true) # no immediate for now
325
+ puts 'line after immediate'
326
+ a = 3
327
+ square(a)
328
+
329
+ class MyClass
330
+ def initialize(x)
331
+ @x = x
332
+ end
337
333
  end
338
- end
339
- $trepanning.debugger
340
- m = MyClass.new(5)
341
- raise RuntimeError # To see how we handle post-mortem debugging.
334
+ $trepanning.debugger
335
+ m = MyClass.new(5)
336
+ raise RuntimeError # To see how we handle post-mortem debugging.
342
337
  end