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.
Files changed (274) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGES +34 -0
  3. data/ChangeLog +875 -0
  4. data/README.textile +59 -0
  5. data/Rakefile +215 -0
  6. data/app/.gitignore +1 -0
  7. data/app/cmd_parse.kpeg +241 -0
  8. data/app/cmd_parse.rb +212 -0
  9. data/app/cmd_parser.rb +1948 -0
  10. data/app/complete.rb +79 -0
  11. data/app/default.rb +90 -0
  12. data/app/display.rb +148 -0
  13. data/app/eventbuffer.rb +147 -0
  14. data/app/frame.rb +166 -0
  15. data/app/irb.rb +114 -0
  16. data/app/options.rb +200 -0
  17. data/app/run.rb +74 -0
  18. data/app/util.rb +65 -0
  19. data/bin/.gitignore +1 -0
  20. data/bin/trepan8 +115 -0
  21. data/data/.gitignore +1 -0
  22. data/data/irbrc +41 -0
  23. data/interface/.gitignore +1 -0
  24. data/interface/base_intf.rb +109 -0
  25. data/interface/client.rb +82 -0
  26. data/interface/comcodes.rb +20 -0
  27. data/interface/script.rb +110 -0
  28. data/interface/server.rb +147 -0
  29. data/interface/user.rb +165 -0
  30. data/io/base_io.rb +148 -0
  31. data/io/input.rb +158 -0
  32. data/io/null_output.rb +46 -0
  33. data/io/string_array.rb +156 -0
  34. data/io/tcpclient.rb +129 -0
  35. data/io/tcpfns.rb +33 -0
  36. data/io/tcpserver.rb +141 -0
  37. data/lib/debugger.rb +8 -0
  38. data/lib/trepanning.rb +283 -0
  39. data/processor/.gitignore +1 -0
  40. data/processor/command-ruby-debug/breakpoints.rb +155 -0
  41. data/processor/command-ruby-debug/catchpoint.rb +55 -0
  42. data/processor/command-ruby-debug/condition.rb +49 -0
  43. data/processor/command-ruby-debug/control.rb +31 -0
  44. data/processor/command-ruby-debug/display.rb +120 -0
  45. data/processor/command-ruby-debug/enable.rb +202 -0
  46. data/processor/command-ruby-debug/frame.rb +199 -0
  47. data/processor/command-ruby-debug/help.rb +63 -0
  48. data/processor/command-ruby-debug/info.rb +359 -0
  49. data/processor/command-ruby-debug/method.rb +84 -0
  50. data/processor/command-ruby-debug/reload.rb +40 -0
  51. data/processor/command-ruby-debug/save.rb +90 -0
  52. data/processor/command-ruby-debug/set.rb +237 -0
  53. data/processor/command-ruby-debug/show.rb +251 -0
  54. data/processor/command-ruby-debug/source.rb +36 -0
  55. data/processor/command-ruby-debug/threads.rb +189 -0
  56. data/processor/command-ruby-debug/trace.rb +57 -0
  57. data/processor/command-ruby-debug/variables.rb +199 -0
  58. data/processor/command.rb +270 -0
  59. data/processor/command/.gitignore +1 -0
  60. data/processor/command/alias.rb +54 -0
  61. data/processor/command/backtrace.rb +123 -0
  62. data/processor/command/base/cmd.rb +177 -0
  63. data/processor/command/base/subcmd.rb +230 -0
  64. data/processor/command/base/submgr.rb +188 -0
  65. data/processor/command/base/subsubcmd.rb +128 -0
  66. data/processor/command/base/subsubmgr.rb +199 -0
  67. data/processor/command/break.rb +114 -0
  68. data/processor/command/catch.rb +71 -0
  69. data/processor/command/complete.rb +39 -0
  70. data/processor/command/continue.rb +57 -0
  71. data/processor/command/directory.rb +50 -0
  72. data/processor/command/disable.rb +85 -0
  73. data/processor/command/display.rb +78 -0
  74. data/processor/command/down.rb +54 -0
  75. data/processor/command/edit.rb +79 -0
  76. data/processor/command/enable.rb +48 -0
  77. data/processor/command/eval.rb +90 -0
  78. data/processor/command/exit.rb +66 -0
  79. data/processor/command/finish.rb +59 -0
  80. data/processor/command/frame.rb +97 -0
  81. data/processor/command/help.rb +230 -0
  82. data/processor/command/help/.gitignore +1 -0
  83. data/processor/command/help/README +10 -0
  84. data/processor/command/help/command.txt +58 -0
  85. data/processor/command/help/examples.txt +16 -0
  86. data/processor/command/help/filename.txt +40 -0
  87. data/processor/command/help/location.txt +37 -0
  88. data/processor/command/help/suffixes.txt +17 -0
  89. data/processor/command/info.rb +28 -0
  90. data/processor/command/info_subcmd/.gitignore +1 -0
  91. data/processor/command/info_subcmd/args.rb +39 -0
  92. data/processor/command/info_subcmd/breakpoints.rb +80 -0
  93. data/processor/command/info_subcmd/catch.rb +36 -0
  94. data/processor/command/info_subcmd/files.rb +39 -0
  95. data/processor/command/info_subcmd/globals.rb +64 -0
  96. data/processor/command/info_subcmd/line.rb +30 -0
  97. data/processor/command/info_subcmd/locals.rb +69 -0
  98. data/processor/command/info_subcmd/macro.rb +62 -0
  99. data/processor/command/info_subcmd/program.rb +51 -0
  100. data/processor/command/info_subcmd/ruby.rb +57 -0
  101. data/processor/command/info_subcmd/source.rb +74 -0
  102. data/processor/command/info_subcmd/stack.rb +25 -0
  103. data/processor/command/info_subcmd/threads.rb +75 -0
  104. data/processor/command/kill.rb +78 -0
  105. data/processor/command/list.rb +117 -0
  106. data/processor/command/macro.rb +68 -0
  107. data/processor/command/next.rb +79 -0
  108. data/processor/command/parsetree.rb +56 -0
  109. data/processor/command/pp.rb +40 -0
  110. data/processor/command/pr.rb +37 -0
  111. data/processor/command/ps.rb +40 -0
  112. data/processor/command/restart.rb +86 -0
  113. data/processor/command/save.rb +58 -0
  114. data/processor/command/set.rb +47 -0
  115. data/processor/command/set_subcmd/.gitignore +1 -0
  116. data/processor/command/set_subcmd/abbrev.rb +25 -0
  117. data/processor/command/set_subcmd/auto.rb +27 -0
  118. data/processor/command/set_subcmd/auto_subcmd/.gitignore +1 -0
  119. data/processor/command/set_subcmd/auto_subcmd/eval.rb +53 -0
  120. data/processor/command/set_subcmd/auto_subcmd/irb.rb +33 -0
  121. data/processor/command/set_subcmd/auto_subcmd/list.rb +33 -0
  122. data/processor/command/set_subcmd/basename.rb +25 -0
  123. data/processor/command/set_subcmd/callstyle.rb +46 -0
  124. data/processor/command/set_subcmd/confirm.rb +24 -0
  125. data/processor/command/set_subcmd/debug.rb +47 -0
  126. data/processor/command/set_subcmd/different.rb +61 -0
  127. data/processor/command/set_subcmd/highlight.rb +43 -0
  128. data/processor/command/set_subcmd/max.rb +26 -0
  129. data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
  130. data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
  131. data/processor/command/set_subcmd/max_subcmd/string.rb +76 -0
  132. data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
  133. data/processor/command/set_subcmd/reload.rb +42 -0
  134. data/processor/command/set_subcmd/timer.rb +58 -0
  135. data/processor/command/set_subcmd/trace.rb +37 -0
  136. data/processor/command/set_subcmd/trace_subcmd/buffer.rb +42 -0
  137. data/processor/command/set_subcmd/trace_subcmd/print.rb +41 -0
  138. data/processor/command/shell.rb +139 -0
  139. data/processor/command/show.rb +39 -0
  140. data/processor/command/show_subcmd/.gitignore +1 -0
  141. data/processor/command/show_subcmd/abbrev.rb +20 -0
  142. data/processor/command/show_subcmd/alias.rb +46 -0
  143. data/processor/command/show_subcmd/args.rb +34 -0
  144. data/processor/command/show_subcmd/auto.rb +28 -0
  145. data/processor/command/show_subcmd/auto_subcmd/eval.rb +27 -0
  146. data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
  147. data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
  148. data/processor/command/show_subcmd/basename.rb +20 -0
  149. data/processor/command/show_subcmd/callstyle.rb +22 -0
  150. data/processor/command/show_subcmd/confirm.rb +18 -0
  151. data/processor/command/show_subcmd/debug.rb +26 -0
  152. data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
  153. data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
  154. data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
  155. data/processor/command/show_subcmd/different.rb +26 -0
  156. data/processor/command/show_subcmd/directories.rb +22 -0
  157. data/processor/command/show_subcmd/highlight.rb +24 -0
  158. data/processor/command/show_subcmd/max.rb +27 -0
  159. data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
  160. data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
  161. data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
  162. data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
  163. data/processor/command/show_subcmd/reload.rb +18 -0
  164. data/processor/command/show_subcmd/timer.rb +18 -0
  165. data/processor/command/show_subcmd/trace.rb +29 -0
  166. data/processor/command/show_subcmd/trace_subcmd/buffer.rb +65 -0
  167. data/processor/command/show_subcmd/trace_subcmd/print.rb +23 -0
  168. data/processor/command/show_subcmd/version.rb +23 -0
  169. data/processor/command/source.rb +134 -0
  170. data/processor/command/step.rb +81 -0
  171. data/processor/command/tbreak.rb +19 -0
  172. data/processor/command/unalias.rb +44 -0
  173. data/processor/command/undisplay.rb +59 -0
  174. data/processor/command/up.rb +72 -0
  175. data/processor/default.rb +56 -0
  176. data/processor/display.rb +17 -0
  177. data/processor/eval.rb +113 -0
  178. data/processor/eventbuf.rb +105 -0
  179. data/processor/frame.rb +172 -0
  180. data/processor/help.rb +92 -0
  181. data/processor/helper.rb +76 -0
  182. data/processor/hook.rb +134 -0
  183. data/processor/load_cmds.rb +258 -0
  184. data/processor/location.rb +174 -0
  185. data/processor/main.rb +455 -0
  186. data/processor/mock.rb +136 -0
  187. data/processor/msg.rb +61 -0
  188. data/processor/processor.rb +674 -0
  189. data/processor/running.rb +168 -0
  190. data/processor/stepping.rb +18 -0
  191. data/processor/subcmd.rb +161 -0
  192. data/processor/validate.rb +355 -0
  193. data/processor/virtual.rb +34 -0
  194. data/test/data/.gitignore +1 -0
  195. data/test/data/break_bad.cmd +19 -0
  196. data/test/data/break_bad.right +29 -0
  197. data/test/data/break_loop_bug.cmd +5 -0
  198. data/test/data/break_loop_bug.right +15 -0
  199. data/test/data/dollar-0.right +2 -0
  200. data/test/data/dollar-0a.right +2 -0
  201. data/test/data/dollar-0b.right +2 -0
  202. data/test/data/edit.cmd +14 -0
  203. data/test/data/edit.right +24 -0
  204. data/test/data/file-with-space.cmd +6 -0
  205. data/test/data/file-with-space.right +4 -0
  206. data/test/data/printvar.cmd +17 -0
  207. data/test/data/printvar.right +31 -0
  208. data/test/data/raise.cmd +11 -0
  209. data/test/data/raise.right +19 -0
  210. data/test/data/source.cmd +5 -0
  211. data/test/data/source.right +18 -0
  212. data/test/data/stepping-1.9.right +50 -0
  213. data/test/data/stepping.cmd +21 -0
  214. data/test/data/stepping.right +48 -0
  215. data/test/data/trepan8-save.1 +6 -0
  216. data/test/example/bp_loop_issue.rb +3 -0
  217. data/test/example/break-bug.rb +7 -0
  218. data/test/example/brkpt-class-bug.rb +8 -0
  219. data/test/example/classes.rb +11 -0
  220. data/test/example/dollar-0.rb +5 -0
  221. data/test/example/except-bug1.rb +4 -0
  222. data/test/example/except-bug2.rb +7 -0
  223. data/test/example/file with space.rb +1 -0
  224. data/test/example/gcd.rb +18 -0
  225. data/test/example/info-var-bug.rb +47 -0
  226. data/test/example/info-var-bug2.rb +2 -0
  227. data/test/example/null.rb +1 -0
  228. data/test/example/pm-bug.rb +3 -0
  229. data/test/example/pm.rb +11 -0
  230. data/test/example/raise.rb +3 -0
  231. data/test/integration/.gitignore +4 -0
  232. data/test/integration/config.yaml +8 -0
  233. data/test/integration/helper.rb +154 -0
  234. data/test/integration/test-break_bad.rb +26 -0
  235. data/test/integration/test-dollar-0.rb +31 -0
  236. data/test/integration/test-edit.rb +17 -0
  237. data/test/integration/test-file-with-space.rb +26 -0
  238. data/test/integration/test-printvar.rb +17 -0
  239. data/test/integration/test-raise.rb +21 -0
  240. data/test/integration/test-source.rb +16 -0
  241. data/test/integration/test-stepping.rb +24 -0
  242. data/test/unit/.gitignore +1 -0
  243. data/test/unit/cmd-helper.rb +52 -0
  244. data/test/unit/mock-helper.rb +12 -0
  245. data/test/unit/test-app-cmd_parse.rb +97 -0
  246. data/test/unit/test-app-cmd_parser.rb +23 -0
  247. data/test/unit/test-app-complete.rb +39 -0
  248. data/test/unit/test-app-frame.rb +32 -0
  249. data/test/unit/test-app-options.rb +92 -0
  250. data/test/unit/test-app-run.rb +14 -0
  251. data/test/unit/test-app-util.rb +44 -0
  252. data/test/unit/test-base-cmd.rb +45 -0
  253. data/test/unit/test-base-subcmd.rb +57 -0
  254. data/test/unit/test-base-submgr.rb +23 -0
  255. data/test/unit/test-base-subsubcmd.rb +17 -0
  256. data/test/unit/test-cmd-alias.rb +48 -0
  257. data/test/unit/test-cmd-exit.rb +27 -0
  258. data/test/unit/test-cmd-help.rb +104 -0
  259. data/test/unit/test-cmd-kill.rb +46 -0
  260. data/test/unit/test-cmd-source.rb +34 -0
  261. data/test/unit/test-completion.rb +42 -0
  262. data/test/unit/test-intf-user.rb +46 -0
  263. data/test/unit/test-io-input.rb +27 -0
  264. data/test/unit/test-io-tcp.rb +33 -0
  265. data/test/unit/test-io-tcpclient.rb +54 -0
  266. data/test/unit/test-io-tcpfns.rb +17 -0
  267. data/test/unit/test-io-tcpserver.rb +50 -0
  268. data/test/unit/test-proc-eval.rb +36 -0
  269. data/test/unit/test-proc-hook.rb +30 -0
  270. data/test/unit/test-proc-load_cmds.rb +50 -0
  271. data/test/unit/test-proc-location.rb +79 -0
  272. data/test/unit/test-subcmd-help.rb +44 -0
  273. data/trepan8.gemspec +52 -0
  274. 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
@@ -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
@@ -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
+