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
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# Communication status codes
|
|
5
|
+
module Trepanning
|
|
6
|
+
# Most of these go from debugged process to front-end
|
|
7
|
+
# client interface. COMMAND goes the other way.
|
|
8
|
+
module RemoteCommunication
|
|
9
|
+
unless defined?(PRINT)
|
|
10
|
+
PRINT = '.'
|
|
11
|
+
COMMAND = 'C'
|
|
12
|
+
CONFIRM_TRUE = 'Y'
|
|
13
|
+
CONFIRM_FALSE = 'N'
|
|
14
|
+
CONFIRM_REPLY = '?'
|
|
15
|
+
QUIT = 'q'
|
|
16
|
+
PROMPT = 'p'
|
|
17
|
+
RESTART = 'r'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/interface/script.rb
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# Module for reading debugger scripts
|
|
5
|
+
|
|
6
|
+
# Our local modules
|
|
7
|
+
require 'rubygems'; require 'require_relative'
|
|
8
|
+
require_relative 'base_intf'
|
|
9
|
+
require_relative '../io/input'
|
|
10
|
+
require_relative '../io/string_array'
|
|
11
|
+
|
|
12
|
+
# Interface when reading debugger scripts
|
|
13
|
+
class Trepan::ScriptInterface < Trepan::Interface
|
|
14
|
+
attr_accessor :opts, :output
|
|
15
|
+
|
|
16
|
+
DEFAULT_OPTS = {
|
|
17
|
+
:abort_on_error => true,
|
|
18
|
+
:confirm_val => false,
|
|
19
|
+
:verbose => false
|
|
20
|
+
} unless defined?(DEFAULT_OPTS)
|
|
21
|
+
|
|
22
|
+
def initialize(script_name, out=nil, opts={})
|
|
23
|
+
@opts = DEFAULT_OPTS.merge(opts)
|
|
24
|
+
|
|
25
|
+
at_exit { finalize }
|
|
26
|
+
@script_name = script_name
|
|
27
|
+
@input_lineno = 0
|
|
28
|
+
@input = opts[:input] ||
|
|
29
|
+
Trepan::UserInput.open(script_name, :line_edit => false)
|
|
30
|
+
@buffer_output = []
|
|
31
|
+
unless @opts[:verbose] or out
|
|
32
|
+
out = Trepan::StringArrayOutput.open(@buffer_output)
|
|
33
|
+
end
|
|
34
|
+
super(@input, out, @opts)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Closes input only.
|
|
38
|
+
def close
|
|
39
|
+
@input.close
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Called when a dangerous action is about to be done, to make
|
|
43
|
+
# sure it's okay.
|
|
44
|
+
#
|
|
45
|
+
# Could look also look for interactive input and
|
|
46
|
+
# use that. For now, though we'll simplify.
|
|
47
|
+
def confirm(prompt, default)
|
|
48
|
+
@opts[:default_confirm]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Common routine for reporting debugger error messages.
|
|
52
|
+
#
|
|
53
|
+
def errmsg(msg, prefix="*** ")
|
|
54
|
+
# self.verbose shows lines so we don't have to duplicate info
|
|
55
|
+
# here. Perhaps there should be a 'terse' mode to never show
|
|
56
|
+
# position info.
|
|
57
|
+
mess = if not @opts[:verbose]
|
|
58
|
+
location = ("%s:%s: Error in source command file" %
|
|
59
|
+
[@script_name, @input_lineno])
|
|
60
|
+
"%s%s:\n%s%s" % [prefix, location, prefix, msg]
|
|
61
|
+
else
|
|
62
|
+
"%s%s" % [prefix, msg]
|
|
63
|
+
end
|
|
64
|
+
msg(mess)
|
|
65
|
+
# FIXME: should we just set a flag and report eof? to be more
|
|
66
|
+
# consistent with File and IO?
|
|
67
|
+
raise IOError if @opts[:abort_on_error]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def interactive? ; false end
|
|
71
|
+
|
|
72
|
+
# Script interface to read a command. `prompt' is a parameter for
|
|
73
|
+
# compatibilty and is ignored.
|
|
74
|
+
def read_command(prompt='')
|
|
75
|
+
@input_lineno += 1
|
|
76
|
+
line = readline
|
|
77
|
+
if @opts[:verbose]
|
|
78
|
+
script_name =
|
|
79
|
+
if @opts[:basename]
|
|
80
|
+
File.basename(@script_name)
|
|
81
|
+
else
|
|
82
|
+
@script_name
|
|
83
|
+
end
|
|
84
|
+
location = "%s line %s" % [script_name, @input_lineno]
|
|
85
|
+
msg('+ %s: %s' % [location, line])
|
|
86
|
+
end
|
|
87
|
+
# Do something with history?
|
|
88
|
+
return line
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Script interface to read a line. `prompt' is a parameter for
|
|
92
|
+
# compatibilty and is ignored.
|
|
93
|
+
#
|
|
94
|
+
# Could decide make this look for interactive input?
|
|
95
|
+
def readline(prompt='')
|
|
96
|
+
begin
|
|
97
|
+
return input.readline().chomp
|
|
98
|
+
rescue EOFError
|
|
99
|
+
@eof = true
|
|
100
|
+
raise EOFError
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Demo
|
|
106
|
+
if __FILE__ == $0
|
|
107
|
+
intf = Trepan::ScriptInterface.new(__FILE__)
|
|
108
|
+
line = intf.readline()
|
|
109
|
+
print "Line read: ", line
|
|
110
|
+
end
|
data/interface/server.rb
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# Our local modules
|
|
5
|
+
require 'rubygems'; require 'require_relative'
|
|
6
|
+
require_relative 'base_intf'
|
|
7
|
+
require_relative 'comcodes'
|
|
8
|
+
require_relative '../io/input'
|
|
9
|
+
require_relative '../io/tcpserver'
|
|
10
|
+
|
|
11
|
+
# Mfifoserver = import_relative('fifoserver', '..io', 'pydbgr')
|
|
12
|
+
|
|
13
|
+
# Interface for debugging a program but having user control
|
|
14
|
+
# reside outside of the debugged process, possibly on another
|
|
15
|
+
# computer
|
|
16
|
+
class Trepan::ServerInterface < Trepan::Interface
|
|
17
|
+
|
|
18
|
+
include Trepanning::RemoteCommunication
|
|
19
|
+
|
|
20
|
+
DEFAULT_INIT_CONNECTION_OPTS = {
|
|
21
|
+
:io => 'TCP'
|
|
22
|
+
} unless defined?(DEFAULT_INIT_CONNECTION_OPTS)
|
|
23
|
+
|
|
24
|
+
def initialize(inout=nil, out=nil, connection_opts={})
|
|
25
|
+
|
|
26
|
+
@connection_opts = DEFAULT_INIT_CONNECTION_OPTS.merge(connection_opts)
|
|
27
|
+
|
|
28
|
+
at_exit { finalize }
|
|
29
|
+
@inout =
|
|
30
|
+
if inout
|
|
31
|
+
inout
|
|
32
|
+
else
|
|
33
|
+
server_type = @connection_opts[:io]
|
|
34
|
+
# FIXME: complete this.
|
|
35
|
+
# if 'FIFO' == server_type
|
|
36
|
+
# FIFOServer.new
|
|
37
|
+
# else
|
|
38
|
+
Trepan::TCPDbgServer.new(@connection_opts)
|
|
39
|
+
# end
|
|
40
|
+
end
|
|
41
|
+
# For Compatability
|
|
42
|
+
@output = @inout
|
|
43
|
+
@input = @inout
|
|
44
|
+
@interactive = true # Or at least so we think initially
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Closes both input and output
|
|
48
|
+
def close
|
|
49
|
+
if @inout && @inout.connected?
|
|
50
|
+
@inout.write(QUIT + 'bye')
|
|
51
|
+
@inout.close
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def closed?
|
|
56
|
+
@inout.closed?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Called when a dangerous action is about to be done to make sure
|
|
60
|
+
# it's okay. `prompt' is printed; user response is returned.
|
|
61
|
+
# FIXME: make common routine for this and user.rb
|
|
62
|
+
def confirm(prompt, default)
|
|
63
|
+
while true
|
|
64
|
+
begin
|
|
65
|
+
write_confirm(prompt, default)
|
|
66
|
+
reply = readline(nil).strip.downcase
|
|
67
|
+
rescue EOFError
|
|
68
|
+
return default
|
|
69
|
+
end
|
|
70
|
+
if YES.member?(reply)
|
|
71
|
+
return true
|
|
72
|
+
elsif NO.member?(reply)
|
|
73
|
+
return false
|
|
74
|
+
else
|
|
75
|
+
msg "Please answer 'yes' or 'no'. Try again."
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
return default
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Return true if we are connected
|
|
82
|
+
def connected?
|
|
83
|
+
:connected == @inout.state
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# print exit annotation
|
|
87
|
+
def finalize(last_wishes=QUIT)
|
|
88
|
+
@inout.writeline(last_wishes) if connected?
|
|
89
|
+
close
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def input_eof?
|
|
93
|
+
false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# used to write to a debugger that is connected to this
|
|
97
|
+
# server; `str' written will have a newline added to it
|
|
98
|
+
def msg(msg)
|
|
99
|
+
@inout.writeline(PRINT + msg)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# used to write to a debugger that is connected to this
|
|
103
|
+
# server; `str' written will not have a newline added to it
|
|
104
|
+
def msg_nocr(msg)
|
|
105
|
+
@inout.write(PRINT + msg)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def read_command(prompt)
|
|
109
|
+
readline(prompt)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def read_data
|
|
113
|
+
@inout.read_dat
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def readline(prompt, add_to_history=true)
|
|
117
|
+
if prompt
|
|
118
|
+
write_prompt(prompt)
|
|
119
|
+
end
|
|
120
|
+
coded_line = @inout.read_msg()
|
|
121
|
+
@read_ctrl = coded_line[0..0]
|
|
122
|
+
coded_line[1..-1]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Return connected
|
|
126
|
+
def state
|
|
127
|
+
@inout.state
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def write_prompt(prompt)
|
|
131
|
+
@inout.write(PROMPT + prompt)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def write_confirm(prompt, default)
|
|
135
|
+
if default
|
|
136
|
+
code = CONFIRM_TRUE
|
|
137
|
+
else
|
|
138
|
+
code = CONFIRM_FALSE
|
|
139
|
+
end
|
|
140
|
+
@inout.write(code + prompt)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Demo
|
|
145
|
+
if __FILE__ == $0
|
|
146
|
+
intf = Trepan::ServerInterface.new(nil, nil, :open => false)
|
|
147
|
+
end
|
data/interface/user.rb
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# Interface when communicating with the user.
|
|
5
|
+
|
|
6
|
+
# Our local modules
|
|
7
|
+
|
|
8
|
+
require 'rubygems'; require 'require_relative'
|
|
9
|
+
require_relative 'base_intf'
|
|
10
|
+
require_relative '../io/input'
|
|
11
|
+
|
|
12
|
+
# Interface when communicating with the user.
|
|
13
|
+
class Trepan::UserInterface < Trepan::Interface
|
|
14
|
+
|
|
15
|
+
DEFAULT_USER_OPTS = {
|
|
16
|
+
:readline => true, # Try to use GNU Readline?
|
|
17
|
+
|
|
18
|
+
# The below are only used if we want and have readline support.
|
|
19
|
+
# See method Trepan::GNU_readline? below.
|
|
20
|
+
:histsize => 256, # Use gdb's default setting
|
|
21
|
+
:file_history => '.trepan8_hist', # where history file lives
|
|
22
|
+
# Note a directory will
|
|
23
|
+
# be appended
|
|
24
|
+
:history_save => true # do we save the history?
|
|
25
|
+
} unless defined?(DEFAULT_USER_OPTS)
|
|
26
|
+
|
|
27
|
+
def initialize(inp=nil, out=nil, opts={})
|
|
28
|
+
super(inp, out, opts)
|
|
29
|
+
@opts = DEFAULT_USER_OPTS.merge(opts)
|
|
30
|
+
@input = if inp.class.ancestors.member?(Trepan::InputBase)
|
|
31
|
+
inp
|
|
32
|
+
else
|
|
33
|
+
Trepan::UserInput.open(inp, {:readline => opts[:readline]})
|
|
34
|
+
end
|
|
35
|
+
if Trepan::GNU_readline? && @opts[:complete]
|
|
36
|
+
Readline.completion_proc = @opts[:complete]
|
|
37
|
+
read_history
|
|
38
|
+
end
|
|
39
|
+
## at_exit { finalize }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def closed?
|
|
43
|
+
@input.closed? && @output.closed?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Called when a dangerous action is about to be done, to make
|
|
47
|
+
# sure it's okay. Expect a yes/no answer to `prompt' which is printed,
|
|
48
|
+
# suffixed with a question mark and the default value. The user
|
|
49
|
+
# response converted to a boolean is returned.
|
|
50
|
+
# FIXME: make common routine for this and server.rb
|
|
51
|
+
def confirm(prompt, default)
|
|
52
|
+
default_str = default ? 'Y/n' : 'N/y'
|
|
53
|
+
while true do
|
|
54
|
+
begin
|
|
55
|
+
response = readline('%s (%s) ' % [prompt, default_str])
|
|
56
|
+
rescue EOFError
|
|
57
|
+
return default
|
|
58
|
+
end
|
|
59
|
+
response = response.strip.downcase
|
|
60
|
+
|
|
61
|
+
# We don't catch "Yes, I'm sure" or "NO!", but I leave that
|
|
62
|
+
# as an exercise for the reader.
|
|
63
|
+
break if YES_OR_NO.member?(response)
|
|
64
|
+
msg "Please answer 'yes' or 'no'. Try again."
|
|
65
|
+
end
|
|
66
|
+
return YES.member?(response)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Read a saved Readline history file into Readline. The history
|
|
70
|
+
# file will be created if it doesn't already exist.
|
|
71
|
+
# Much of this code follows what's done in ruby-debug.
|
|
72
|
+
def read_history
|
|
73
|
+
unless @histfile
|
|
74
|
+
dirname = ENV['HOME'] || ENV['HOMEPATH'] || File.expand_path('~')
|
|
75
|
+
@histfile = File.join(dirname, @opts[:file_history])
|
|
76
|
+
end
|
|
77
|
+
@histsize ||= (ENV['HISTSIZE'] ? ENV['HISTSIZE'].to_i : @opts[:histsize])
|
|
78
|
+
Readline.completion_proc = @opts[:complete]
|
|
79
|
+
if File.exists?(@histfile)
|
|
80
|
+
lines = IO::readlines(@histfile).last(@histsize).collect do
|
|
81
|
+
|line| line.chomp
|
|
82
|
+
end
|
|
83
|
+
Readline::HISTORY.push(*lines)
|
|
84
|
+
@history_io = File.new(@histfile, "a")
|
|
85
|
+
else
|
|
86
|
+
@history_io = File.new(@histfile, "w")
|
|
87
|
+
end
|
|
88
|
+
@history_io.sync = true
|
|
89
|
+
@history_save = @opts[:history_save]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def save_history
|
|
93
|
+
if @histfile
|
|
94
|
+
lines = Readline::HISTORY.to_a
|
|
95
|
+
lines = lines[-@histsize, @histsize] if lines.size > @histsize
|
|
96
|
+
begin
|
|
97
|
+
open(@histfile, 'w') do |file|
|
|
98
|
+
Readline::HISTORY.to_a.last(@histsize).each do |line|
|
|
99
|
+
file.puts line
|
|
100
|
+
end
|
|
101
|
+
end if defined?(@history_save) and @history_save
|
|
102
|
+
rescue
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def finalize(last_wishes=nil)
|
|
108
|
+
# ?? print gdb-style exit annotation if annotate = 2?
|
|
109
|
+
if Trepan::GNU_readline? && @history_save
|
|
110
|
+
save_history
|
|
111
|
+
end
|
|
112
|
+
super
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def interactive? ; @input.interactive? end
|
|
116
|
+
|
|
117
|
+
def read_command(prompt='')
|
|
118
|
+
readline(prompt)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def readline(prompt='')
|
|
122
|
+
@output.flush
|
|
123
|
+
if @input.line_edit && @opts[:readline]
|
|
124
|
+
if Trepan::GNU_readline? && @opts[:complete]
|
|
125
|
+
Readline.completion_proc = @opts[:complete]
|
|
126
|
+
end
|
|
127
|
+
# rb-readline 0.4.0 has bugs
|
|
128
|
+
begin
|
|
129
|
+
@input.readline(prompt)
|
|
130
|
+
rescue Exception => e
|
|
131
|
+
@output.write("Exception: #{e} in readline\n")
|
|
132
|
+
''
|
|
133
|
+
end
|
|
134
|
+
else
|
|
135
|
+
@output.write(prompt) if prompt and prompt.size > 0
|
|
136
|
+
@input.readline
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Demo
|
|
143
|
+
if __FILE__ == $0
|
|
144
|
+
intf = Trepan::UserInterface.new
|
|
145
|
+
intf.errmsg("Houston, we have a problem here!")
|
|
146
|
+
if ARGV.size > 0
|
|
147
|
+
begin
|
|
148
|
+
line = intf.readline("Type something: ")
|
|
149
|
+
rescue EOFError
|
|
150
|
+
puts "No input, got EOF"
|
|
151
|
+
else
|
|
152
|
+
puts "You typed: #{line}"
|
|
153
|
+
end
|
|
154
|
+
puts "EOF is now: %s" % intf.input.eof?.inspect
|
|
155
|
+
unless intf.input.eof?
|
|
156
|
+
line = intf.confirm("Are you sure", false)
|
|
157
|
+
puts "You typed: #{line}"
|
|
158
|
+
puts "EOF is now: %s" % intf.input.eof?.inspect
|
|
159
|
+
line = intf.confirm("Are you not sure", true)
|
|
160
|
+
puts "You typed: #{line}"
|
|
161
|
+
puts "EOF is now: %s" % intf.input.eof?.inspect
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
puts "User interface closed?: #{intf.closed?}"
|
|
165
|
+
end
|
data/io/base_io.rb
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
# classes to support communication to and from the debugger. This
|
|
3
|
+
# communcation might be to/from another process or another computer.
|
|
4
|
+
# And reading may be from a debugger command script.
|
|
5
|
+
#
|
|
6
|
+
# For example, we'd like to support Sockets, and serial lines and file
|
|
7
|
+
# reading, as well a readline-type input. Encryption and Authentication
|
|
8
|
+
# methods might decorate some of the communication channels.
|
|
9
|
+
#
|
|
10
|
+
# Some ideas originiated as part of Matt Fleming's 2006 Google Summer of
|
|
11
|
+
# Code project.
|
|
12
|
+
|
|
13
|
+
module Trepan
|
|
14
|
+
|
|
15
|
+
NotImplementedMessage = 'This method must be overriden in a subclass' unless
|
|
16
|
+
defined?(NotImplementedMessage)
|
|
17
|
+
|
|
18
|
+
class InputBase
|
|
19
|
+
attr_reader :input
|
|
20
|
+
attr_reader :line_edit
|
|
21
|
+
|
|
22
|
+
DEFAULT_OPTS = {
|
|
23
|
+
:line_edit => false,
|
|
24
|
+
} unless defined?(DEFAULT_OPTS)
|
|
25
|
+
|
|
26
|
+
def initialize(inp, opts={})
|
|
27
|
+
@opts = DEFAULT_OPTS.merge(opts)
|
|
28
|
+
@input = inp
|
|
29
|
+
@line_edit = opts[:line_edit]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def close
|
|
33
|
+
@input.close unless @input.closed?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def eof?
|
|
37
|
+
begin
|
|
38
|
+
@input.eof?
|
|
39
|
+
rescue IOError
|
|
40
|
+
true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Read a line of input. EOFError will be raised on EOF.
|
|
45
|
+
#
|
|
46
|
+
# Note that we don't support prompting first. Instead, arrange
|
|
47
|
+
# to call Trepan::Output.write() first with the prompt. If
|
|
48
|
+
# `use_raw' is set raw_input() will be used in that is supported
|
|
49
|
+
# by the specific input input. If this option is left None as is
|
|
50
|
+
# normally expected the value from the class initialization is
|
|
51
|
+
# used.
|
|
52
|
+
def readline
|
|
53
|
+
@input.readline
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# This is an abstract class that specifies debugger output.
|
|
58
|
+
class OutputBase
|
|
59
|
+
attr_accessor :flush_after_write
|
|
60
|
+
attr_reader :output
|
|
61
|
+
def initialize(out, opts={})
|
|
62
|
+
@output = out
|
|
63
|
+
@flush_after_write = false
|
|
64
|
+
@eof = false
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def close
|
|
68
|
+
@output.close if @output
|
|
69
|
+
@eof = true
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def eof?
|
|
73
|
+
@eof
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def flush
|
|
77
|
+
@output.flush
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Use this to set where to write to. output can be a
|
|
81
|
+
# file object or a string. This code raises IOError on error.
|
|
82
|
+
def write(*args)
|
|
83
|
+
@output.print(*args)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# used to write to a debugger that is connected to this
|
|
87
|
+
# `str' written will have a newline added to it
|
|
88
|
+
#
|
|
89
|
+
def writeline(msg)
|
|
90
|
+
@output.write("%s\n" % msg)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# This is an abstract class that specifies debugger input output when
|
|
95
|
+
# handled by the same channel, e.g. a socket or tty.
|
|
96
|
+
#
|
|
97
|
+
class InOutBase
|
|
98
|
+
|
|
99
|
+
def initialize(inout, opts={})
|
|
100
|
+
@opts = DEFAULT_OPTS.merge(opts)
|
|
101
|
+
@inout = inout
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def close
|
|
105
|
+
@inout.close() if @inout
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def eof?
|
|
109
|
+
begin
|
|
110
|
+
@input.eof?
|
|
111
|
+
rescue IOError
|
|
112
|
+
true
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def flush
|
|
117
|
+
@inout.flush
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Read a line of input. EOFError will be raised on EOF.
|
|
121
|
+
#
|
|
122
|
+
# Note that we don't support prompting first. Instead, arrange to
|
|
123
|
+
# call DebuggerOutput.write() first with the prompt. If `use_raw'
|
|
124
|
+
# is set raw_input() will be used in that is supported by the
|
|
125
|
+
# specific input input. If this option is left nil as is normally
|
|
126
|
+
# expected the value from the class initialization is used.
|
|
127
|
+
def readline(use_raw=nil)
|
|
128
|
+
@input.readline
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Use this to set where to write to. output can be a
|
|
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
|
|
135
|
+
# file object or a string. This code raises IOError on error.
|
|
136
|
+
def write(*args)
|
|
137
|
+
@inout.write(*args)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# used to write to a debugger that is connected to this
|
|
141
|
+
# server; `str' written will have a newline added to it
|
|
142
|
+
def writeline( msg)
|
|
143
|
+
@inout.write("%s\n" % msg)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
|