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
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
@@ -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