rb8-trepanning 0.1.3
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.
- data/.gitignore +3 -0
- data/CHANGES +34 -0
- data/ChangeLog +875 -0
- data/README.textile +59 -0
- data/Rakefile +215 -0
- data/app/.gitignore +1 -0
- data/app/cmd_parse.kpeg +241 -0
- data/app/cmd_parse.rb +212 -0
- data/app/cmd_parser.rb +1948 -0
- data/app/complete.rb +79 -0
- data/app/default.rb +90 -0
- data/app/display.rb +148 -0
- data/app/eventbuffer.rb +147 -0
- data/app/frame.rb +166 -0
- data/app/irb.rb +114 -0
- data/app/options.rb +200 -0
- data/app/run.rb +74 -0
- data/app/util.rb +65 -0
- data/bin/.gitignore +1 -0
- data/bin/trepan8 +115 -0
- data/data/.gitignore +1 -0
- data/data/irbrc +41 -0
- data/interface/.gitignore +1 -0
- data/interface/base_intf.rb +109 -0
- data/interface/client.rb +82 -0
- data/interface/comcodes.rb +20 -0
- data/interface/script.rb +110 -0
- data/interface/server.rb +147 -0
- data/interface/user.rb +165 -0
- data/io/base_io.rb +148 -0
- data/io/input.rb +158 -0
- data/io/null_output.rb +46 -0
- data/io/string_array.rb +156 -0
- data/io/tcpclient.rb +129 -0
- data/io/tcpfns.rb +33 -0
- data/io/tcpserver.rb +141 -0
- data/lib/debugger.rb +8 -0
- data/lib/trepanning.rb +283 -0
- data/processor/.gitignore +1 -0
- data/processor/command-ruby-debug/breakpoints.rb +155 -0
- data/processor/command-ruby-debug/catchpoint.rb +55 -0
- data/processor/command-ruby-debug/condition.rb +49 -0
- data/processor/command-ruby-debug/control.rb +31 -0
- data/processor/command-ruby-debug/display.rb +120 -0
- data/processor/command-ruby-debug/enable.rb +202 -0
- data/processor/command-ruby-debug/frame.rb +199 -0
- data/processor/command-ruby-debug/help.rb +63 -0
- data/processor/command-ruby-debug/info.rb +359 -0
- data/processor/command-ruby-debug/method.rb +84 -0
- data/processor/command-ruby-debug/reload.rb +40 -0
- data/processor/command-ruby-debug/save.rb +90 -0
- data/processor/command-ruby-debug/set.rb +237 -0
- data/processor/command-ruby-debug/show.rb +251 -0
- data/processor/command-ruby-debug/source.rb +36 -0
- data/processor/command-ruby-debug/threads.rb +189 -0
- data/processor/command-ruby-debug/trace.rb +57 -0
- data/processor/command-ruby-debug/variables.rb +199 -0
- data/processor/command.rb +270 -0
- data/processor/command/.gitignore +1 -0
- data/processor/command/alias.rb +54 -0
- data/processor/command/backtrace.rb +123 -0
- data/processor/command/base/cmd.rb +177 -0
- data/processor/command/base/subcmd.rb +230 -0
- data/processor/command/base/submgr.rb +188 -0
- data/processor/command/base/subsubcmd.rb +128 -0
- data/processor/command/base/subsubmgr.rb +199 -0
- data/processor/command/break.rb +114 -0
- data/processor/command/catch.rb +71 -0
- data/processor/command/complete.rb +39 -0
- data/processor/command/continue.rb +57 -0
- data/processor/command/directory.rb +50 -0
- data/processor/command/disable.rb +85 -0
- data/processor/command/display.rb +78 -0
- data/processor/command/down.rb +54 -0
- data/processor/command/edit.rb +79 -0
- data/processor/command/enable.rb +48 -0
- data/processor/command/eval.rb +90 -0
- data/processor/command/exit.rb +66 -0
- data/processor/command/finish.rb +59 -0
- data/processor/command/frame.rb +97 -0
- data/processor/command/help.rb +230 -0
- data/processor/command/help/.gitignore +1 -0
- data/processor/command/help/README +10 -0
- data/processor/command/help/command.txt +58 -0
- data/processor/command/help/examples.txt +16 -0
- data/processor/command/help/filename.txt +40 -0
- data/processor/command/help/location.txt +37 -0
- data/processor/command/help/suffixes.txt +17 -0
- data/processor/command/info.rb +28 -0
- data/processor/command/info_subcmd/.gitignore +1 -0
- data/processor/command/info_subcmd/args.rb +39 -0
- data/processor/command/info_subcmd/breakpoints.rb +80 -0
- data/processor/command/info_subcmd/catch.rb +36 -0
- data/processor/command/info_subcmd/files.rb +39 -0
- data/processor/command/info_subcmd/globals.rb +64 -0
- data/processor/command/info_subcmd/line.rb +30 -0
- data/processor/command/info_subcmd/locals.rb +69 -0
- data/processor/command/info_subcmd/macro.rb +62 -0
- data/processor/command/info_subcmd/program.rb +51 -0
- data/processor/command/info_subcmd/ruby.rb +57 -0
- data/processor/command/info_subcmd/source.rb +74 -0
- data/processor/command/info_subcmd/stack.rb +25 -0
- data/processor/command/info_subcmd/threads.rb +75 -0
- data/processor/command/kill.rb +78 -0
- data/processor/command/list.rb +117 -0
- data/processor/command/macro.rb +68 -0
- data/processor/command/next.rb +79 -0
- data/processor/command/parsetree.rb +56 -0
- data/processor/command/pp.rb +40 -0
- data/processor/command/pr.rb +37 -0
- data/processor/command/ps.rb +40 -0
- data/processor/command/restart.rb +86 -0
- data/processor/command/save.rb +58 -0
- data/processor/command/set.rb +47 -0
- data/processor/command/set_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/abbrev.rb +25 -0
- data/processor/command/set_subcmd/auto.rb +27 -0
- data/processor/command/set_subcmd/auto_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +53 -0
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +33 -0
- data/processor/command/set_subcmd/auto_subcmd/list.rb +33 -0
- data/processor/command/set_subcmd/basename.rb +25 -0
- data/processor/command/set_subcmd/callstyle.rb +46 -0
- data/processor/command/set_subcmd/confirm.rb +24 -0
- data/processor/command/set_subcmd/debug.rb +47 -0
- data/processor/command/set_subcmd/different.rb +61 -0
- data/processor/command/set_subcmd/highlight.rb +43 -0
- data/processor/command/set_subcmd/max.rb +26 -0
- data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
- data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
- data/processor/command/set_subcmd/max_subcmd/string.rb +76 -0
- data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
- data/processor/command/set_subcmd/reload.rb +42 -0
- data/processor/command/set_subcmd/timer.rb +58 -0
- data/processor/command/set_subcmd/trace.rb +37 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +42 -0
- data/processor/command/set_subcmd/trace_subcmd/print.rb +41 -0
- data/processor/command/shell.rb +139 -0
- data/processor/command/show.rb +39 -0
- data/processor/command/show_subcmd/.gitignore +1 -0
- data/processor/command/show_subcmd/abbrev.rb +20 -0
- data/processor/command/show_subcmd/alias.rb +46 -0
- data/processor/command/show_subcmd/args.rb +34 -0
- data/processor/command/show_subcmd/auto.rb +28 -0
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +27 -0
- data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
- data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
- data/processor/command/show_subcmd/basename.rb +20 -0
- data/processor/command/show_subcmd/callstyle.rb +22 -0
- data/processor/command/show_subcmd/confirm.rb +18 -0
- data/processor/command/show_subcmd/debug.rb +26 -0
- data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
- data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
- data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
- data/processor/command/show_subcmd/different.rb +26 -0
- data/processor/command/show_subcmd/directories.rb +22 -0
- data/processor/command/show_subcmd/highlight.rb +24 -0
- data/processor/command/show_subcmd/max.rb +27 -0
- data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
- data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
- data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
- data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
- data/processor/command/show_subcmd/reload.rb +18 -0
- data/processor/command/show_subcmd/timer.rb +18 -0
- data/processor/command/show_subcmd/trace.rb +29 -0
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +65 -0
- data/processor/command/show_subcmd/trace_subcmd/print.rb +23 -0
- data/processor/command/show_subcmd/version.rb +23 -0
- data/processor/command/source.rb +134 -0
- data/processor/command/step.rb +81 -0
- data/processor/command/tbreak.rb +19 -0
- data/processor/command/unalias.rb +44 -0
- data/processor/command/undisplay.rb +59 -0
- data/processor/command/up.rb +72 -0
- data/processor/default.rb +56 -0
- data/processor/display.rb +17 -0
- data/processor/eval.rb +113 -0
- data/processor/eventbuf.rb +105 -0
- data/processor/frame.rb +172 -0
- data/processor/help.rb +92 -0
- data/processor/helper.rb +76 -0
- data/processor/hook.rb +134 -0
- data/processor/load_cmds.rb +258 -0
- data/processor/location.rb +174 -0
- data/processor/main.rb +455 -0
- data/processor/mock.rb +136 -0
- data/processor/msg.rb +61 -0
- data/processor/processor.rb +674 -0
- data/processor/running.rb +168 -0
- data/processor/stepping.rb +18 -0
- data/processor/subcmd.rb +161 -0
- data/processor/validate.rb +355 -0
- data/processor/virtual.rb +34 -0
- data/test/data/.gitignore +1 -0
- data/test/data/break_bad.cmd +19 -0
- data/test/data/break_bad.right +29 -0
- data/test/data/break_loop_bug.cmd +5 -0
- data/test/data/break_loop_bug.right +15 -0
- data/test/data/dollar-0.right +2 -0
- data/test/data/dollar-0a.right +2 -0
- data/test/data/dollar-0b.right +2 -0
- data/test/data/edit.cmd +14 -0
- data/test/data/edit.right +24 -0
- data/test/data/file-with-space.cmd +6 -0
- data/test/data/file-with-space.right +4 -0
- data/test/data/printvar.cmd +17 -0
- data/test/data/printvar.right +31 -0
- data/test/data/raise.cmd +11 -0
- data/test/data/raise.right +19 -0
- data/test/data/source.cmd +5 -0
- data/test/data/source.right +18 -0
- data/test/data/stepping-1.9.right +50 -0
- data/test/data/stepping.cmd +21 -0
- data/test/data/stepping.right +48 -0
- data/test/data/trepan8-save.1 +6 -0
- data/test/example/bp_loop_issue.rb +3 -0
- data/test/example/break-bug.rb +7 -0
- data/test/example/brkpt-class-bug.rb +8 -0
- data/test/example/classes.rb +11 -0
- data/test/example/dollar-0.rb +5 -0
- data/test/example/except-bug1.rb +4 -0
- data/test/example/except-bug2.rb +7 -0
- data/test/example/file with space.rb +1 -0
- data/test/example/gcd.rb +18 -0
- data/test/example/info-var-bug.rb +47 -0
- data/test/example/info-var-bug2.rb +2 -0
- data/test/example/null.rb +1 -0
- data/test/example/pm-bug.rb +3 -0
- data/test/example/pm.rb +11 -0
- data/test/example/raise.rb +3 -0
- data/test/integration/.gitignore +4 -0
- data/test/integration/config.yaml +8 -0
- data/test/integration/helper.rb +154 -0
- data/test/integration/test-break_bad.rb +26 -0
- data/test/integration/test-dollar-0.rb +31 -0
- data/test/integration/test-edit.rb +17 -0
- data/test/integration/test-file-with-space.rb +26 -0
- data/test/integration/test-printvar.rb +17 -0
- data/test/integration/test-raise.rb +21 -0
- data/test/integration/test-source.rb +16 -0
- data/test/integration/test-stepping.rb +24 -0
- data/test/unit/.gitignore +1 -0
- data/test/unit/cmd-helper.rb +52 -0
- data/test/unit/mock-helper.rb +12 -0
- data/test/unit/test-app-cmd_parse.rb +97 -0
- data/test/unit/test-app-cmd_parser.rb +23 -0
- data/test/unit/test-app-complete.rb +39 -0
- data/test/unit/test-app-frame.rb +32 -0
- data/test/unit/test-app-options.rb +92 -0
- data/test/unit/test-app-run.rb +14 -0
- data/test/unit/test-app-util.rb +44 -0
- data/test/unit/test-base-cmd.rb +45 -0
- data/test/unit/test-base-subcmd.rb +57 -0
- data/test/unit/test-base-submgr.rb +23 -0
- data/test/unit/test-base-subsubcmd.rb +17 -0
- data/test/unit/test-cmd-alias.rb +48 -0
- data/test/unit/test-cmd-exit.rb +27 -0
- data/test/unit/test-cmd-help.rb +104 -0
- data/test/unit/test-cmd-kill.rb +46 -0
- data/test/unit/test-cmd-source.rb +34 -0
- data/test/unit/test-completion.rb +42 -0
- data/test/unit/test-intf-user.rb +46 -0
- data/test/unit/test-io-input.rb +27 -0
- data/test/unit/test-io-tcp.rb +33 -0
- data/test/unit/test-io-tcpclient.rb +54 -0
- data/test/unit/test-io-tcpfns.rb +17 -0
- data/test/unit/test-io-tcpserver.rb +50 -0
- data/test/unit/test-proc-eval.rb +36 -0
- data/test/unit/test-proc-hook.rb +30 -0
- data/test/unit/test-proc-load_cmds.rb +50 -0
- data/test/unit/test-proc-location.rb +79 -0
- data/test/unit/test-subcmd-help.rb +44 -0
- data/trepan8.gemspec +52 -0
- metadata +391 -0
data/io/tcpfns.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
# Subsidiary routines used to "pack" and "unpack" TCP messages.
|
|
4
|
+
|
|
5
|
+
module Trepanning
|
|
6
|
+
module TCPPacking
|
|
7
|
+
|
|
8
|
+
unless defined?(TCP_MAX_PACKET)
|
|
9
|
+
TCP_MAX_PACKET = 8192 # Largest size for a recv
|
|
10
|
+
LOG_MAX_MSG = Math.log10(TCP_MAX_PACKET).ceil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def pack_msg(msg)
|
|
14
|
+
fmt = '%%%dd' % LOG_MAX_MSG # A funny way of writing: '%4d'
|
|
15
|
+
(fmt % msg.size) + msg
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def unpack_msg(buf)
|
|
19
|
+
length = Integer(buf[0...LOG_MAX_MSG])
|
|
20
|
+
data = buf[LOG_MAX_MSG..LOG_MAX_MSG+length]
|
|
21
|
+
buf = buf[LOG_MAX_MSG+length..-1]
|
|
22
|
+
[buf, data]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Demo
|
|
28
|
+
if __FILE__ == $0
|
|
29
|
+
include Trepanning::TCPPacking
|
|
30
|
+
msg = "Hi there!"
|
|
31
|
+
puts unpack_msg(pack_msg(msg))[1] == msg
|
|
32
|
+
end
|
|
33
|
+
|
data/io/tcpserver.rb
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
# Debugger Server Input/Output interface.
|
|
4
|
+
|
|
5
|
+
require 'socket'
|
|
6
|
+
require 'rubygems'; require 'require_relative'
|
|
7
|
+
require_relative '../app/default' # For host and port
|
|
8
|
+
require_relative 'base_io'
|
|
9
|
+
require_relative 'tcpfns'
|
|
10
|
+
|
|
11
|
+
module Trepan
|
|
12
|
+
# Debugger Server Input/Output Socket.
|
|
13
|
+
class TCPDbgServer < Trepan::InOutBase
|
|
14
|
+
|
|
15
|
+
include Trepanning::TCPPacking
|
|
16
|
+
|
|
17
|
+
unless defined?(SERVER_SOCKET_OPTS)
|
|
18
|
+
DEFAULT_INIT_OPTS = {:open => true}
|
|
19
|
+
|
|
20
|
+
SERVER_SOCKET_OPTS = {
|
|
21
|
+
:host => Trepan::DEFAULT_SETTINGS[:host],
|
|
22
|
+
:port => Trepan::DEFAULT_SETTINGS[:port], # A non-privileged port
|
|
23
|
+
:timeout => 5, # FIXME: not used
|
|
24
|
+
:reuse => true, # FIXME: not used. Allow port to be resued on close?
|
|
25
|
+
# Python has: 'posix' == os.name
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
attr_reader :state
|
|
30
|
+
|
|
31
|
+
def initialize(opts={})
|
|
32
|
+
@opts = DEFAULT_INIT_OPTS.merge(opts)
|
|
33
|
+
@input = @output = @session = nil
|
|
34
|
+
@buf = '' # Read buffer
|
|
35
|
+
@state = :disconnected
|
|
36
|
+
@port = nil # Current port in use
|
|
37
|
+
@host = nil # current host in use
|
|
38
|
+
@line_edit = false
|
|
39
|
+
open(@opts) if @opts[:open]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def connected?
|
|
43
|
+
:connected == @state
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Closes server connection.
|
|
48
|
+
def close
|
|
49
|
+
@state = :closing
|
|
50
|
+
@session.close if @session
|
|
51
|
+
@state = :disconnected
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def open(opts={})
|
|
55
|
+
@opts = SERVER_SOCKET_OPTS.merge(opts)
|
|
56
|
+
@host = @opts[:host]
|
|
57
|
+
@port = @opts[:port]
|
|
58
|
+
@server = TCPServer.new(@host, @port)
|
|
59
|
+
# @server.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, 5)
|
|
60
|
+
# # @opts[:timeout])
|
|
61
|
+
@state = :listening
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Read one message unit. It's possible however that
|
|
65
|
+
# more than one message will be set in a receive, so we will
|
|
66
|
+
# have to buffer that for the next read.
|
|
67
|
+
# EOFError will be raised on EOF.
|
|
68
|
+
def read_msg
|
|
69
|
+
wait_for_connect unless connected?
|
|
70
|
+
while !@buf || @buf.empty?
|
|
71
|
+
@buf, info = @session.recvfrom(TCP_MAX_PACKET)
|
|
72
|
+
end
|
|
73
|
+
@buf, data = unpack_msg(@buf)
|
|
74
|
+
data
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def wait_for_connect
|
|
78
|
+
@input = @output = @session = @server.accept
|
|
79
|
+
@state = :connected
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# This method the debugger uses to write. In contrast to
|
|
83
|
+
# writeline, no newline is added to the end to `str'. Also
|
|
84
|
+
# msg doesn't have to be a string.
|
|
85
|
+
def write(msg)
|
|
86
|
+
wait_for_connect() unless connected?
|
|
87
|
+
# FIXME: do we have to check the size of msg and split output?
|
|
88
|
+
@session.print(pack_msg(msg))
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def writeline(msg)
|
|
92
|
+
write(msg + "\n")
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Demo
|
|
99
|
+
if __FILE__ == $0
|
|
100
|
+
include Trepanning::TCPPacking
|
|
101
|
+
server = Trepan::TCPDbgServer.new({ :open => false,
|
|
102
|
+
:port => 1027,
|
|
103
|
+
:host => 'localhost'
|
|
104
|
+
})
|
|
105
|
+
if ARGV.size > 0
|
|
106
|
+
puts 'Listening for connection...'
|
|
107
|
+
server.open
|
|
108
|
+
threads = []
|
|
109
|
+
Thread.new do
|
|
110
|
+
while true do
|
|
111
|
+
begin
|
|
112
|
+
line = server.read_msg.chomp
|
|
113
|
+
puts "got #{line}"
|
|
114
|
+
rescue EOFError
|
|
115
|
+
puts 'Got EOF'
|
|
116
|
+
break
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
threads << Thread.new do
|
|
121
|
+
t = TCPSocket.new('localhost', 1027)
|
|
122
|
+
while true do
|
|
123
|
+
begin
|
|
124
|
+
print "input? "
|
|
125
|
+
line = STDIN.gets
|
|
126
|
+
break if !line || line.chomp == 'quit'
|
|
127
|
+
t.puts(pack_msg(line))
|
|
128
|
+
rescue EOFError
|
|
129
|
+
puts "Got EOF"
|
|
130
|
+
break
|
|
131
|
+
rescue Exception => e
|
|
132
|
+
puts "Got #{e}"
|
|
133
|
+
break
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
t.close
|
|
137
|
+
end
|
|
138
|
+
threads.each {|t| t.join }
|
|
139
|
+
server.close
|
|
140
|
+
end
|
|
141
|
+
end
|
data/lib/debugger.rb
ADDED
data/lib/trepanning.rb
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'pp'
|
|
3
|
+
require 'stringio'
|
|
4
|
+
require 'socket'
|
|
5
|
+
require 'thread'
|
|
6
|
+
require 'ruby-debug-base'
|
|
7
|
+
require 'require_relative'
|
|
8
|
+
require_relative '../interface/script'
|
|
9
|
+
require_relative '../interface/user'
|
|
10
|
+
require_relative '../processor/processor'
|
|
11
|
+
|
|
12
|
+
module Trepan
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
|
|
16
|
+
## FIXME: see if we can put this in app/complete.
|
|
17
|
+
# The method is called when we want to do debugger command completion
|
|
18
|
+
# such as called from GNU Readline with <TAB>.
|
|
19
|
+
def self.completion_method(last_token, leading=nil)
|
|
20
|
+
if leading.nil?
|
|
21
|
+
if Readline.respond_to?(:line_buffer)
|
|
22
|
+
completion =
|
|
23
|
+
Trepan.handler.cmdproc.complete(Readline.line_buffer,
|
|
24
|
+
last_token)
|
|
25
|
+
else
|
|
26
|
+
completion = Trepan.handler.cmdproc.complete(last_token, '')
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
completion = Trepan.handler.cmdproc.complete(leading, last_token)
|
|
30
|
+
end
|
|
31
|
+
if 1 == completion.size
|
|
32
|
+
completion_token = completion[0]
|
|
33
|
+
if last_token.end_with?(' ')
|
|
34
|
+
if last_token.rstrip == completion_token
|
|
35
|
+
# There is nothing more to complete
|
|
36
|
+
[]
|
|
37
|
+
else
|
|
38
|
+
[]
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
[completion_token]
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
# We have multiple completions. Get the last token so that will
|
|
45
|
+
# be presented as a list of completions.
|
|
46
|
+
completion
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
completion_proc = method(:completion_method).to_proc
|
|
50
|
+
## FIXME: figure out how to get at this for testing.
|
|
51
|
+
$trepan_completion_proc = completion_proc
|
|
52
|
+
|
|
53
|
+
opts = {
|
|
54
|
+
:complete => completion_proc,
|
|
55
|
+
:readline => true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@@intf = [Trepan::UserInterface.new(nil, nil, opts)]
|
|
59
|
+
|
|
60
|
+
attr_accessor :handler
|
|
61
|
+
Trepan.handler = Debugger.handler = CommandProcessor.new(@@intf)
|
|
62
|
+
|
|
63
|
+
# gdb-style annotation mode. Used in GNU Emacs interface
|
|
64
|
+
attr_accessor :annotate
|
|
65
|
+
|
|
66
|
+
# in remote mode, wait for the remote connection
|
|
67
|
+
attr_accessor :wait_connection
|
|
68
|
+
|
|
69
|
+
# If start_sentinal is set, it is a string to look for in caller()
|
|
70
|
+
# and is used to see if the call stack is truncated. Is also
|
|
71
|
+
# defined in app/default.rb
|
|
72
|
+
attr_accessor :start_sentinal
|
|
73
|
+
|
|
74
|
+
attr_reader :thread, :control_thread, :cmd_port, :ctrl_port
|
|
75
|
+
|
|
76
|
+
def interface=(value) # :nodoc:
|
|
77
|
+
Debugger.handler.interface = value
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Trepan.start(options) -> bool
|
|
81
|
+
# Trepan.start(options) { ... } -> obj
|
|
82
|
+
#
|
|
83
|
+
# If it's called without a block it returns +true+, unless debugger
|
|
84
|
+
# was already started. If a block is given, it starts debugger and
|
|
85
|
+
# yields to block. When the block is finished executing it stops
|
|
86
|
+
# the debugger with Trepan.stop method.
|
|
87
|
+
#
|
|
88
|
+
# If a block is given, it starts debugger and yields to block. When
|
|
89
|
+
# the block is finished executing it stops the debugger with
|
|
90
|
+
# Trepan.stop method. Inside the block you will probably want to
|
|
91
|
+
# have a call to Trepan.debugger. For example:
|
|
92
|
+
#
|
|
93
|
+
# Trepan.start{debugger; foo} # Stop inside of foo
|
|
94
|
+
#
|
|
95
|
+
# Also, ruby-debug only allows
|
|
96
|
+
# one invocation of debugger at a time; nested Trepan.start's
|
|
97
|
+
# have no effect and you can't use this inside the debugger itself.
|
|
98
|
+
#
|
|
99
|
+
# <i>Note that if you want to stop debugger, you must call
|
|
100
|
+
# Trepan.stop as many time as you called Trepan.start
|
|
101
|
+
# method.</i>
|
|
102
|
+
#
|
|
103
|
+
# +options+ is a hash used to set various debugging options.
|
|
104
|
+
# Set :init true if you want to save ARGV and some variables which
|
|
105
|
+
# make a debugger restart possible. Only the first time :init is set true
|
|
106
|
+
# will values get set. Since ARGV is saved, you should make sure
|
|
107
|
+
# it hasn't been changed before the (first) call.
|
|
108
|
+
# Set :post_mortem true if you want to enter post-mortem debugging
|
|
109
|
+
# on an uncaught exception. Once post-mortem debugging is set, it can't
|
|
110
|
+
# be unset.
|
|
111
|
+
def start(options={}, &block)
|
|
112
|
+
options = Trepan::DEFAULT_START_SETTINGS.merge(options)
|
|
113
|
+
if options[:init]
|
|
114
|
+
Trepan.const_set('ARGV', ARGV.clone) unless
|
|
115
|
+
defined? Trepan::ARGV
|
|
116
|
+
Trepan.const_set('PROG_SCRIPT', $0) unless
|
|
117
|
+
defined? Trepan::PROG_SCRIPT
|
|
118
|
+
Trepan.const_set('INITIAL_DIR', Dir.pwd) unless
|
|
119
|
+
defined? Trepan::INITIAL_DIR
|
|
120
|
+
end
|
|
121
|
+
Trepan.tracing = options[:tracing] unless options[:tracing].nil?
|
|
122
|
+
retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block)
|
|
123
|
+
if options[:post_mortem]
|
|
124
|
+
post_mortem
|
|
125
|
+
end
|
|
126
|
+
return retval
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def started?
|
|
130
|
+
Debugger.started?
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
# Starts a remote debugger.
|
|
135
|
+
#
|
|
136
|
+
def start_remote(host = nil, port = PORT, post_mortem = false)
|
|
137
|
+
return if @thread
|
|
138
|
+
return if started?
|
|
139
|
+
|
|
140
|
+
self.interface = nil
|
|
141
|
+
start
|
|
142
|
+
self.post_mortem if post_mortem
|
|
143
|
+
|
|
144
|
+
if port.kind_of?(Array)
|
|
145
|
+
cmd_port, ctrl_port = port
|
|
146
|
+
else
|
|
147
|
+
cmd_port, ctrl_port = port, port + 1
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
ctrl_port = start_control(host, ctrl_port)
|
|
151
|
+
|
|
152
|
+
yield if block_given?
|
|
153
|
+
|
|
154
|
+
mutex = Mutex.new
|
|
155
|
+
proceed = ConditionVariable.new
|
|
156
|
+
|
|
157
|
+
server = TCPServer.new(host, cmd_port)
|
|
158
|
+
@cmd_port = cmd_port = server.addr[1]
|
|
159
|
+
@thread = Debugger::DebugThread.new do
|
|
160
|
+
while (session = server.accept)
|
|
161
|
+
self.interface = RemoteInterface.new(session)
|
|
162
|
+
if wait_connection
|
|
163
|
+
mutex.synchronize do
|
|
164
|
+
proceed.signal
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
if wait_connection
|
|
170
|
+
mutex.synchronize do
|
|
171
|
+
proceed.wait(mutex)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
alias start_server start_remote
|
|
176
|
+
|
|
177
|
+
def start_control(host = nil, ctrl_port = PORT + 1) # :nodoc:
|
|
178
|
+
raise "Debugger is not started" unless started?
|
|
179
|
+
return @ctrl_port if defined?(@control_thread) && @control_thread
|
|
180
|
+
server = TCPServer.new(host, ctrl_port)
|
|
181
|
+
@ctrl_port = server.addr[1]
|
|
182
|
+
@control_thread = Debugger::DebugThread.new do
|
|
183
|
+
while (session = server.accept)
|
|
184
|
+
interface = RemoteInterface.new(session)
|
|
185
|
+
processor = ControlCommandProcessor.new(interface)
|
|
186
|
+
processor.process_commands
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
@ctrl_port
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
#
|
|
193
|
+
# Connects to the remote debugger
|
|
194
|
+
#
|
|
195
|
+
def start_client(host = 'localhost', port = PORT)
|
|
196
|
+
require "socket"
|
|
197
|
+
interface = Trepan::LocalInterface.new
|
|
198
|
+
socket = TCPSocket.new(host, port)
|
|
199
|
+
puts "Connected."
|
|
200
|
+
|
|
201
|
+
catch(:exit) do
|
|
202
|
+
while (line = socket.gets)
|
|
203
|
+
case line
|
|
204
|
+
when /^PROMPT (.*)$/
|
|
205
|
+
input = interface.read_command($1)
|
|
206
|
+
throw :exit unless input
|
|
207
|
+
socket.puts input
|
|
208
|
+
when /^CONFIRM (.*)$/
|
|
209
|
+
input = interface.confirm($1)
|
|
210
|
+
throw :exit unless input
|
|
211
|
+
socket.puts input
|
|
212
|
+
else
|
|
213
|
+
print line
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
socket.close
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def add_command_file(cmdfile, opts={}, stderr=$stderr)
|
|
221
|
+
unless File.readable?(cmdfile)
|
|
222
|
+
if File.exists?(cmdfile)
|
|
223
|
+
stderr.puts "Command file '#{cmdfile}' is not readable."
|
|
224
|
+
return
|
|
225
|
+
else
|
|
226
|
+
stderr.puts "Command file '#{cmdfile}' does not exist."
|
|
227
|
+
return
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
@@intf << Trepan::ScriptInterface.new(cmdfile, @output, opts)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def add_startup_files()
|
|
234
|
+
seen = {}
|
|
235
|
+
cwd_initfile = File.join('.', Trepan::CMD_INITFILE_BASE)
|
|
236
|
+
[cwd_initfile, Trepan::CMD_INITFILE].each do |initfile|
|
|
237
|
+
full_initfile_path = File.expand_path(initfile)
|
|
238
|
+
next if seen[full_initfile_path]
|
|
239
|
+
add_command_file(full_initfile_path) if
|
|
240
|
+
File.readable?(full_initfile_path)
|
|
241
|
+
seen[full_initfile_path] = true
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def process_cmdfile_setting(settings)
|
|
246
|
+
p settings
|
|
247
|
+
puts caller
|
|
248
|
+
exit
|
|
249
|
+
settings[:cmdfiles].each do |item|
|
|
250
|
+
cmdfile, opts =
|
|
251
|
+
if item.kind_of?(Array)
|
|
252
|
+
item
|
|
253
|
+
else
|
|
254
|
+
[item, {}]
|
|
255
|
+
end
|
|
256
|
+
add_command_file(cmdfile, opts)
|
|
257
|
+
end if settings.member?(:cmdfiles)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
module Kernel
|
|
263
|
+
|
|
264
|
+
# Enters the debugger in the current thread after _steps_ line events occur.
|
|
265
|
+
# Before entering the debugger startup script is read.
|
|
266
|
+
#
|
|
267
|
+
# Setting _steps_ to 0 will cause a break in the debugger subroutine
|
|
268
|
+
# and not wait for a line event to occur. You will have to go "up 1"
|
|
269
|
+
# in order to be back in your debugged program rather than the
|
|
270
|
+
# debugger. Settings _steps_ to 0 could be useful you want to stop
|
|
271
|
+
# right after the last statement in some scope, because the next
|
|
272
|
+
# step will take you out of some scope.
|
|
273
|
+
def debugger(steps = 1)
|
|
274
|
+
Trepan.start unless Trepan.started?
|
|
275
|
+
Trepan.add_startup_files
|
|
276
|
+
if 0 == steps
|
|
277
|
+
Debugger.current_context.stop_frame = 0
|
|
278
|
+
else
|
|
279
|
+
Debugger.current_context.stop_next = steps
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
alias breakpoint debugger unless respond_to?(:breakpoint)
|
|
283
|
+
end
|