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/input.rb
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# Debugger user/command-oriented input possibly attached to IO-style
|
|
5
|
+
# input or GNU Readline.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
require 'rubygems'; require 'require_relative'
|
|
9
|
+
require_relative 'base_io'
|
|
10
|
+
|
|
11
|
+
module Trepan
|
|
12
|
+
|
|
13
|
+
# Debugger user/command-oriented input possibly attached to IO-style
|
|
14
|
+
# input or GNU Readline.
|
|
15
|
+
class UserInput < Trepan::InputBase
|
|
16
|
+
|
|
17
|
+
@@readline_finalized = false
|
|
18
|
+
|
|
19
|
+
def initialize(inp, opts={})
|
|
20
|
+
@opts = DEFAULT_OPTS.merge(opts)
|
|
21
|
+
@input = inp || STDIN
|
|
22
|
+
@eof = false
|
|
23
|
+
@line_edit = @opts[:line_edit]
|
|
24
|
+
@use_readline = @opts[:readline]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def closed?; @input.closed? end
|
|
28
|
+
def eof?; @eof end
|
|
29
|
+
|
|
30
|
+
def interactive?
|
|
31
|
+
@input.respond_to?(:isatty) && @input.isatty
|
|
32
|
+
end
|
|
33
|
+
# Read a line of input. EOFError will be raised on EOF.
|
|
34
|
+
def readline(prompt='')
|
|
35
|
+
raise EOFError if eof?
|
|
36
|
+
begin
|
|
37
|
+
if @line_edit && @use_readline
|
|
38
|
+
line = Readline.readline(prompt, true)
|
|
39
|
+
else
|
|
40
|
+
line = @input.gets
|
|
41
|
+
end
|
|
42
|
+
rescue EOFError
|
|
43
|
+
rescue => e
|
|
44
|
+
puts $!.backtrace
|
|
45
|
+
puts "Exception caught #{e.inspect}"
|
|
46
|
+
@eof = true
|
|
47
|
+
end
|
|
48
|
+
@eof = !line
|
|
49
|
+
raise EOFError if eof?
|
|
50
|
+
return line
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class << self
|
|
54
|
+
# Use this to set where to read from.
|
|
55
|
+
#
|
|
56
|
+
# Set opts[:line_edit] if you want this input to interact with
|
|
57
|
+
# GNU-like readline library. By default, we will assume to try
|
|
58
|
+
# using readline.
|
|
59
|
+
def open(inp=nil, opts={})
|
|
60
|
+
inp ||= STDIN
|
|
61
|
+
inp = File.new(inp, 'r') if inp.is_a?(String)
|
|
62
|
+
opts[:line_edit] = @line_edit =
|
|
63
|
+
inp.respond_to?(:isatty) && inp.isatty && Trepan::GNU_readline?
|
|
64
|
+
self.new(inp, opts)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def finalize
|
|
68
|
+
if defined?(RbReadline) && !@@readline_finalized
|
|
69
|
+
begin
|
|
70
|
+
RbReadline.rl_cleanup_after_signal()
|
|
71
|
+
rescue
|
|
72
|
+
end
|
|
73
|
+
begin
|
|
74
|
+
RbReadline.rl_deprep_terminal()
|
|
75
|
+
rescue
|
|
76
|
+
end
|
|
77
|
+
@@readline_finalized = true
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
module Trepan
|
|
85
|
+
def suppress_warnings
|
|
86
|
+
original_verbosity = $VERBOSE
|
|
87
|
+
$VERBOSE = nil
|
|
88
|
+
result = yield
|
|
89
|
+
$VERBOSE = original_verbosity
|
|
90
|
+
return result
|
|
91
|
+
end
|
|
92
|
+
module_function :suppress_warnings
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def Trepan::GNU_readline?
|
|
96
|
+
return @use_readline unless @use_readline.nil?
|
|
97
|
+
begin
|
|
98
|
+
require 'rubygems'
|
|
99
|
+
suppress_warnings { require 'rb-readline' }
|
|
100
|
+
@use_readline = true
|
|
101
|
+
rescue LoadError
|
|
102
|
+
begin
|
|
103
|
+
suppress_warnings { require 'readline' }
|
|
104
|
+
@use_readline = true
|
|
105
|
+
rescue LoadError
|
|
106
|
+
@use_readline = false
|
|
107
|
+
return false
|
|
108
|
+
end
|
|
109
|
+
else
|
|
110
|
+
if @use_readline
|
|
111
|
+
# Returns current line buffer
|
|
112
|
+
def Readline.line_buffer
|
|
113
|
+
RbReadline.rl_line_buffer
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
at_exit { Trepan::UserInput::finalize }
|
|
117
|
+
return true
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Demo
|
|
122
|
+
if __FILE__ == $0
|
|
123
|
+
puts 'Have GNU is: %s' % Trepan::GNU_readline?
|
|
124
|
+
inp = Trepan::UserInput.open(__FILE__, :line_edit => false)
|
|
125
|
+
line = inp.readline
|
|
126
|
+
puts line
|
|
127
|
+
inp.close
|
|
128
|
+
filename = 'input.py'
|
|
129
|
+
begin
|
|
130
|
+
Trepan::UserInput.open(filename)
|
|
131
|
+
rescue
|
|
132
|
+
puts "Can't open #{filename} for reading: #{$!}"
|
|
133
|
+
end
|
|
134
|
+
inp = Trepan::UserInput.open(__FILE__, :line_edit => false)
|
|
135
|
+
while true
|
|
136
|
+
begin
|
|
137
|
+
inp.readline
|
|
138
|
+
rescue EOFError
|
|
139
|
+
break
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
begin
|
|
143
|
+
inp.readline
|
|
144
|
+
rescue EOFError
|
|
145
|
+
puts 'EOF handled correctly'
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
if ARGV.size > 0
|
|
149
|
+
inp = Trepan::UserInput.open
|
|
150
|
+
begin
|
|
151
|
+
print "Type some characters: "
|
|
152
|
+
line = inp.readline()
|
|
153
|
+
puts "You typed: %s" % line
|
|
154
|
+
rescue EOFError
|
|
155
|
+
puts 'Got EOF'
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
data/io/null_output.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# Nukes output. Used for example in sourcing where you don't want
|
|
5
|
+
# to see output.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
require 'rubygems'; require 'require_relative'
|
|
9
|
+
require_relative 'base_io'
|
|
10
|
+
|
|
11
|
+
class Trepan::OutputNull < Trepan::OutputBase
|
|
12
|
+
def initialize(out, opts={})
|
|
13
|
+
@closed = false
|
|
14
|
+
super
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def close
|
|
18
|
+
@closed = true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def closed?
|
|
22
|
+
!!@closed
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def flush
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Use this to set where to write to. output can be a
|
|
29
|
+
# file object or a string. This code raises IOError on error.
|
|
30
|
+
def write(*args)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# used to write to a debugger that is connected to this
|
|
34
|
+
# `str' written will have a newline added to it
|
|
35
|
+
#
|
|
36
|
+
def writeline( msg)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Demo it
|
|
41
|
+
if __FILE__ == $0
|
|
42
|
+
output = Trepan::OutputNull.new(nil)
|
|
43
|
+
p output
|
|
44
|
+
output.write("Invisible")
|
|
45
|
+
output.writeline("Invisible")
|
|
46
|
+
end
|
data/io/string_array.rb
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# Simulate I/O using lists of strings.
|
|
5
|
+
|
|
6
|
+
require 'rubygems'; require 'require_relative'
|
|
7
|
+
require_relative 'base_io'
|
|
8
|
+
|
|
9
|
+
# Simulate I/O using an array of strings. Sort of like StringIO, but
|
|
10
|
+
# even simplier.
|
|
11
|
+
class Trepan::StringArrayInput < Trepan::InputBase
|
|
12
|
+
|
|
13
|
+
def initialize(inp, opts={})
|
|
14
|
+
super
|
|
15
|
+
@closed = false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# this close() interface is defined for class compatibility
|
|
19
|
+
def close
|
|
20
|
+
@closed = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def closed?
|
|
24
|
+
@closed
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def eof?
|
|
28
|
+
@closed || @input.empty?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Nothing to do here. Interface is for compatibility
|
|
32
|
+
def flush ; end
|
|
33
|
+
|
|
34
|
+
# Read a line of input. EOFError will be raised on EOF.
|
|
35
|
+
# Note that we don't support prompting
|
|
36
|
+
def readline
|
|
37
|
+
raise EOFError if eof?
|
|
38
|
+
if @input.empty?
|
|
39
|
+
raise EOFError
|
|
40
|
+
end
|
|
41
|
+
line = @input.shift
|
|
42
|
+
return line
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class << self
|
|
46
|
+
# Use this to set where to read from.
|
|
47
|
+
def open(inp, opts={})
|
|
48
|
+
if inp.is_a?(Array)
|
|
49
|
+
return self.new(inp)
|
|
50
|
+
else
|
|
51
|
+
raise IOError, "Invalid input type (%s) for %s" % [inp.class, inp]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Simulate I/O using an array of strings. Sort of like StringIO, but
|
|
58
|
+
# even simplier.
|
|
59
|
+
class Trepan::StringArrayOutput < Trepan::OutputBase
|
|
60
|
+
|
|
61
|
+
def initialize(out=[], opts={})
|
|
62
|
+
super
|
|
63
|
+
@closed = false
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Nothing to do here. Interface is for compatibility
|
|
67
|
+
def close
|
|
68
|
+
@closed = true
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def closed?
|
|
72
|
+
@closed
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def eof?
|
|
76
|
+
@closed || @output.empty?
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Nothing to do here. Interface is for compatibility
|
|
80
|
+
def flush ; end
|
|
81
|
+
|
|
82
|
+
# This method the debugger uses to write. In contrast to
|
|
83
|
+
# writeline, no newline is added to the end to `str'.
|
|
84
|
+
#
|
|
85
|
+
def write(msg)
|
|
86
|
+
raise ValueError if @closed
|
|
87
|
+
@output << msg
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# used to write to a debugger that is connected to this
|
|
91
|
+
# server; Here, we use the null string '' as an indicator of a
|
|
92
|
+
# newline.
|
|
93
|
+
def writeline(msg)
|
|
94
|
+
write(msg)
|
|
95
|
+
write('')
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class << self
|
|
99
|
+
# Use this to set where to write to. output can be a
|
|
100
|
+
# file object or a string. This code raises IOError on error.
|
|
101
|
+
#
|
|
102
|
+
# If another file was previously open upon calling this open,
|
|
103
|
+
# that will be stacked and will come back into use after
|
|
104
|
+
# a close_write().
|
|
105
|
+
def open(output=[])
|
|
106
|
+
if output.is_a?(Array)
|
|
107
|
+
return self.new(output)
|
|
108
|
+
else
|
|
109
|
+
raise IOError, ("Invalid output type (%s) for %s" %
|
|
110
|
+
[output.class, output])
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Demo
|
|
117
|
+
if __FILE__ == $0
|
|
118
|
+
inp = Trepan::StringArrayInput.open(['Now is the time', 'for all good men'])
|
|
119
|
+
line = inp.readline
|
|
120
|
+
p line
|
|
121
|
+
line = inp.readline
|
|
122
|
+
p line
|
|
123
|
+
begin
|
|
124
|
+
line = inp.readline
|
|
125
|
+
rescue EOFError
|
|
126
|
+
puts 'EOF hit on read'
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
out = Trepan::StringArrayOutput.open
|
|
130
|
+
p out.output
|
|
131
|
+
# line = io.readline('Type some more characters: ')
|
|
132
|
+
out.writeline('Hello, world!')
|
|
133
|
+
p out.output
|
|
134
|
+
out.write('Hello');
|
|
135
|
+
p out.output
|
|
136
|
+
out.writeline(', again.');
|
|
137
|
+
p out.output
|
|
138
|
+
# io.open_write(sys.stdout)
|
|
139
|
+
out.flush_after_write = true
|
|
140
|
+
out.write('Last hello')
|
|
141
|
+
puts "Output is closed? #{out.closed?}"
|
|
142
|
+
out.close
|
|
143
|
+
p out.output
|
|
144
|
+
begin
|
|
145
|
+
out.writeline("You won't see me")
|
|
146
|
+
rescue
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Closing after already closed is okay
|
|
150
|
+
out.close
|
|
151
|
+
puts "Output is closed? #{out.closed?}"
|
|
152
|
+
puts "Input is closed? #{inp.closed?}"
|
|
153
|
+
inp.close
|
|
154
|
+
puts "Input is closed? #{inp.closed?}"
|
|
155
|
+
end
|
|
156
|
+
|
data/io/tcpclient.rb
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
# Debugger Socket Input/Output Interface.
|
|
4
|
+
|
|
5
|
+
require 'socket'
|
|
6
|
+
require 'rubygems'; require 'require_relative'
|
|
7
|
+
require_relative 'base_io'
|
|
8
|
+
require_relative 'tcpfns'
|
|
9
|
+
|
|
10
|
+
module Trepan
|
|
11
|
+
# Debugger Client Input/Output Socket.
|
|
12
|
+
class TCPDbgClient < Trepan::InOutBase
|
|
13
|
+
|
|
14
|
+
include Trepanning::TCPPacking
|
|
15
|
+
|
|
16
|
+
DEFAULT_INIT_OPTS = {:open => true}
|
|
17
|
+
|
|
18
|
+
CLIENT_SOCKET_OPTS = {
|
|
19
|
+
:host => 'localhost', # Symbolic name
|
|
20
|
+
:port => 1027, # Arbitrary non-privileged port
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
attr_reader :state
|
|
24
|
+
|
|
25
|
+
def initialize(opts={})
|
|
26
|
+
@opts = CLIENT_SOCKET_OPTS.merge(opts)
|
|
27
|
+
@addr = nil
|
|
28
|
+
@buf = ''
|
|
29
|
+
@line_edit = false # Our name for GNU readline capability
|
|
30
|
+
@state = :disconnected
|
|
31
|
+
@inout = nil
|
|
32
|
+
open(@opts) if @opts[:open]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Closes both input and output
|
|
36
|
+
def close
|
|
37
|
+
@state = :closing
|
|
38
|
+
@inout.close if @inout
|
|
39
|
+
@state = :disconnected
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def disconnected?
|
|
43
|
+
:disconnected == @state
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def open(opts={})
|
|
47
|
+
@opts = CLIENT_SOCKET_OPTS.merge(opts)
|
|
48
|
+
@host = @opts[:host]
|
|
49
|
+
@port = @opts[:port]
|
|
50
|
+
begin
|
|
51
|
+
@inout = TCPSocket.new(@host, @port)
|
|
52
|
+
@state = :connected
|
|
53
|
+
rescue SystemCallError => e
|
|
54
|
+
raise IOError,
|
|
55
|
+
('Open client for host %s on port %s gives error: %s' %
|
|
56
|
+
[@host, @port, e])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Read one message unit. It's possible however that
|
|
61
|
+
# more than one message will be set in a receive, so we will
|
|
62
|
+
# have to buffer that for the next read.
|
|
63
|
+
# EOFError will be raised on EOF.
|
|
64
|
+
def read_msg
|
|
65
|
+
if @state == :connected
|
|
66
|
+
if !@buf || @buf.empty?
|
|
67
|
+
@buf = @inout.recv(TCP_MAX_PACKET)
|
|
68
|
+
if @buf.empty?
|
|
69
|
+
@state = :disconnected
|
|
70
|
+
raise EOFError
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
@buf, data = unpack_msg(@buf)
|
|
74
|
+
return data
|
|
75
|
+
else
|
|
76
|
+
raise IOError, ("read_msg called in state: %s." % @state.to_s)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# This method the debugger uses to write a message unit.
|
|
81
|
+
def write(msg)
|
|
82
|
+
# FIXME: do we have to check the size of msg and split output?
|
|
83
|
+
@inout.write(pack_msg(msg))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def writeline(msg)
|
|
87
|
+
write(msg + "\n")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Demo
|
|
93
|
+
if __FILE__ == $0
|
|
94
|
+
client = Trepan::TCPDbgClient.new({'open' => false})
|
|
95
|
+
if ARGV.size > 0
|
|
96
|
+
threads = []
|
|
97
|
+
Thread.new do
|
|
98
|
+
server = TCPServer.new('localhost', 1027)
|
|
99
|
+
session = server.accept
|
|
100
|
+
while 'quit' != (line = session.gets)
|
|
101
|
+
session.puts line
|
|
102
|
+
end
|
|
103
|
+
session.close
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
threads << Thread.new do
|
|
107
|
+
print 'Connecting...'
|
|
108
|
+
client.open()
|
|
109
|
+
puts 'connected.'
|
|
110
|
+
while true
|
|
111
|
+
print "input? "
|
|
112
|
+
line = STDIN.gets
|
|
113
|
+
break if line.chomp == 'quit'
|
|
114
|
+
begin
|
|
115
|
+
line = client.writeline(line)
|
|
116
|
+
puts "Got: #{client.read_msg.chomp}"
|
|
117
|
+
rescue EOFError
|
|
118
|
+
puts "Got EOF"
|
|
119
|
+
break
|
|
120
|
+
rescue Exception => e
|
|
121
|
+
puts "Got #{e}"
|
|
122
|
+
break
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
threads.each {|t| t.join }
|
|
127
|
+
end
|
|
128
|
+
client.close
|
|
129
|
+
end
|