rbx-trepanning 0.2.0-universal-rubinius-2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (312) hide show
  1. data/.gitignore +7 -0
  2. data/ChangeLog +2967 -0
  3. data/LICENSE +25 -0
  4. data/Makefile +13 -0
  5. data/NEWS +105 -0
  6. data/README.textile +34 -0
  7. data/Rakefile +244 -0
  8. data/THANKS +14 -0
  9. data/app/.gitignore +2 -0
  10. data/app/breakpoint.rb +242 -0
  11. data/app/brkptmgr.rb +153 -0
  12. data/app/client.rb +71 -0
  13. data/app/cmd_parse.kpeg +242 -0
  14. data/app/cmd_parse.rb +209 -0
  15. data/app/cmd_parser.rb +2083 -0
  16. data/app/complete.rb +79 -0
  17. data/app/condition.rb +22 -0
  18. data/app/default.rb +71 -0
  19. data/app/display.rb +186 -0
  20. data/app/eventbuffer.rb +147 -0
  21. data/app/file.rb +24 -0
  22. data/app/frame.rb +120 -0
  23. data/app/irb.rb +113 -0
  24. data/app/iseq.rb +188 -0
  25. data/app/method.rb +178 -0
  26. data/app/mock.rb +13 -0
  27. data/app/options.rb +154 -0
  28. data/app/rbx-llvm.rb +163 -0
  29. data/app/run.rb +92 -0
  30. data/app/util.rb +99 -0
  31. data/app/validate.rb +30 -0
  32. data/bin/.gitignore +2 -0
  33. data/bin/trepanx +69 -0
  34. data/data/.gitignore +2 -0
  35. data/data/irbrc +41 -0
  36. data/interface/.gitignore +2 -0
  37. data/interface/client.rb +84 -0
  38. data/interface/comcodes.rb +20 -0
  39. data/interface/script.rb +112 -0
  40. data/interface/server.rb +147 -0
  41. data/interface/user.rb +158 -0
  42. data/interface.rb +109 -0
  43. data/io/.gitignore +3 -0
  44. data/io/input.rb +151 -0
  45. data/io/null_output.rb +46 -0
  46. data/io/string_array.rb +155 -0
  47. data/io/tcpclient.rb +129 -0
  48. data/io/tcpfns.rb +33 -0
  49. data/io/tcpserver.rb +141 -0
  50. data/io.rb +148 -0
  51. data/lib/.gitignore +2 -0
  52. data/lib/trepanning.rb +467 -0
  53. data/processor/.gitignore +3 -0
  54. data/processor/Makefile +7 -0
  55. data/processor/breakpoint.rb +167 -0
  56. data/processor/command/.gitignore +2 -0
  57. data/processor/command/alias.rb +65 -0
  58. data/processor/command/backtrace.rb +68 -0
  59. data/processor/command/base/.gitignore +2 -0
  60. data/processor/command/base/subcmd.rb +226 -0
  61. data/processor/command/base/submgr.rb +185 -0
  62. data/processor/command/base/subsubcmd.rb +125 -0
  63. data/processor/command/base/subsubmgr.rb +196 -0
  64. data/processor/command/break.rb +78 -0
  65. data/processor/command/complete.rb +39 -0
  66. data/processor/command/condition.rb +64 -0
  67. data/processor/command/continue.rb +61 -0
  68. data/processor/command/delete.rb +44 -0
  69. data/processor/command/directory.rb +51 -0
  70. data/processor/command/disable.rb +71 -0
  71. data/processor/command/disassemble.rb +180 -0
  72. data/processor/command/display.rb +84 -0
  73. data/processor/command/down.rb +54 -0
  74. data/processor/command/edit.rb +74 -0
  75. data/processor/command/enable.rb +43 -0
  76. data/processor/command/eval.rb +93 -0
  77. data/processor/command/exit.rb +83 -0
  78. data/processor/command/finish.rb +80 -0
  79. data/processor/command/frame.rb +93 -0
  80. data/processor/command/help/.gitignore +1 -0
  81. data/processor/command/help/README +10 -0
  82. data/processor/command/help/command.txt +58 -0
  83. data/processor/command/help/examples.txt +16 -0
  84. data/processor/command/help/filename.txt +40 -0
  85. data/processor/command/help/location.txt +37 -0
  86. data/processor/command/help/suffixes.txt +17 -0
  87. data/processor/command/help.rb +228 -0
  88. data/processor/command/info.rb +30 -0
  89. data/processor/command/info_subcmd/.gitignore +3 -0
  90. data/processor/command/info_subcmd/breakpoints.rb +103 -0
  91. data/processor/command/info_subcmd/files.rb +219 -0
  92. data/processor/command/info_subcmd/frame.rb +68 -0
  93. data/processor/command/info_subcmd/line.rb +75 -0
  94. data/processor/command/info_subcmd/locals.rb +22 -0
  95. data/processor/command/info_subcmd/macro.rb +62 -0
  96. data/processor/command/info_subcmd/method.rb +71 -0
  97. data/processor/command/info_subcmd/program.rb +51 -0
  98. data/processor/command/info_subcmd/ruby.rb +64 -0
  99. data/processor/command/info_subcmd/source.rb +75 -0
  100. data/processor/command/info_subcmd/stack.rb +25 -0
  101. data/processor/command/info_subcmd/variables.rb +35 -0
  102. data/processor/command/info_subcmd/variables_subcmd/.gitignore +2 -0
  103. data/processor/command/info_subcmd/variables_subcmd/class.rb +42 -0
  104. data/processor/command/info_subcmd/variables_subcmd/constant.rb +42 -0
  105. data/processor/command/info_subcmd/variables_subcmd/globals.rb +69 -0
  106. data/processor/command/info_subcmd/variables_subcmd/instance.rb +42 -0
  107. data/processor/command/info_subcmd/variables_subcmd/locals.rb +80 -0
  108. data/processor/command/kill.rb +79 -0
  109. data/processor/command/list.rb +234 -0
  110. data/processor/command/macro.rb +86 -0
  111. data/processor/command/next.rb +67 -0
  112. data/processor/command/nexti.rb +59 -0
  113. data/processor/command/parsetree.rb +51 -0
  114. data/processor/command/pr.rb +37 -0
  115. data/processor/command/ps.rb +40 -0
  116. data/processor/command/restart.rb +60 -0
  117. data/processor/command/save.rb +58 -0
  118. data/processor/command/server.rb +72 -0
  119. data/processor/command/set.rb +47 -0
  120. data/processor/command/set_subcmd/.gitignore +2 -0
  121. data/processor/command/set_subcmd/abbrev.rb +25 -0
  122. data/processor/command/set_subcmd/auto.rb +33 -0
  123. data/processor/command/set_subcmd/auto_subcmd/.gitignore +2 -0
  124. data/processor/command/set_subcmd/auto_subcmd/dis.rb +33 -0
  125. data/processor/command/set_subcmd/auto_subcmd/eval.rb +53 -0
  126. data/processor/command/set_subcmd/auto_subcmd/irb.rb +33 -0
  127. data/processor/command/set_subcmd/auto_subcmd/list.rb +33 -0
  128. data/processor/command/set_subcmd/basename.rb +25 -0
  129. data/processor/command/set_subcmd/confirm.rb +24 -0
  130. data/processor/command/set_subcmd/debug.rb +26 -0
  131. data/processor/command/set_subcmd/debug_subcmd/.gitignore +2 -0
  132. data/processor/command/set_subcmd/debug_subcmd/dbgr.rb +36 -0
  133. data/processor/command/set_subcmd/debug_subcmd/skip.rb +23 -0
  134. data/processor/command/set_subcmd/debug_subcmd/step.rb +23 -0
  135. data/processor/command/set_subcmd/different.rb +61 -0
  136. data/processor/command/set_subcmd/hidelevel.rb +62 -0
  137. data/processor/command/set_subcmd/highlight.rb +39 -0
  138. data/processor/command/set_subcmd/kernelstep.rb +60 -0
  139. data/processor/command/set_subcmd/max.rb +26 -0
  140. data/processor/command/set_subcmd/max_subcmd/.gitignore +2 -0
  141. data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
  142. data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
  143. data/processor/command/set_subcmd/max_subcmd/string.rb +76 -0
  144. data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
  145. data/processor/command/set_subcmd/reload.rb +42 -0
  146. data/processor/command/set_subcmd/substitute.rb +24 -0
  147. data/processor/command/set_subcmd/substitute_subcmd/.gitignore +3 -0
  148. data/processor/command/set_subcmd/substitute_subcmd/path.rb +56 -0
  149. data/processor/command/set_subcmd/timer.rb +58 -0
  150. data/processor/command/set_subcmd/trace.rb +37 -0
  151. data/processor/command/set_subcmd/trace_subcmd/.gitignore +2 -0
  152. data/processor/command/set_subcmd/trace_subcmd/buffer.rb +42 -0
  153. data/processor/command/set_subcmd/trace_subcmd/print.rb +41 -0
  154. data/processor/command/shell.rb +131 -0
  155. data/processor/command/show.rb +39 -0
  156. data/processor/command/show_subcmd/.gitignore +3 -0
  157. data/processor/command/show_subcmd/abbrev.rb +20 -0
  158. data/processor/command/show_subcmd/aliases.rb +46 -0
  159. data/processor/command/show_subcmd/args.rb +25 -0
  160. data/processor/command/show_subcmd/auto.rb +28 -0
  161. data/processor/command/show_subcmd/auto_subcmd/.gitignore +3 -0
  162. data/processor/command/show_subcmd/auto_subcmd/dis.rb +37 -0
  163. data/processor/command/show_subcmd/auto_subcmd/eval.rb +24 -0
  164. data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
  165. data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
  166. data/processor/command/show_subcmd/basename.rb +20 -0
  167. data/processor/command/show_subcmd/confirm.rb +18 -0
  168. data/processor/command/show_subcmd/debug.rb +26 -0
  169. data/processor/command/show_subcmd/debug_subcmd/.gitignore +3 -0
  170. data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
  171. data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
  172. data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
  173. data/processor/command/show_subcmd/different.rb +26 -0
  174. data/processor/command/show_subcmd/directories.rb +22 -0
  175. data/processor/command/show_subcmd/hidelevel.rb +41 -0
  176. data/processor/command/show_subcmd/highlight.rb +25 -0
  177. data/processor/command/show_subcmd/kernelstep.rb +34 -0
  178. data/processor/command/show_subcmd/max.rb +27 -0
  179. data/processor/command/show_subcmd/max_subcmd/.gitignore +2 -0
  180. data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
  181. data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
  182. data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
  183. data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
  184. data/processor/command/show_subcmd/reload.rb +18 -0
  185. data/processor/command/show_subcmd/timer.rb +18 -0
  186. data/processor/command/show_subcmd/trace.rb +27 -0
  187. data/processor/command/show_subcmd/trace_subcmd/.gitignore +2 -0
  188. data/processor/command/show_subcmd/trace_subcmd/buffer.rb +64 -0
  189. data/processor/command/show_subcmd/trace_subcmd/print.rb +23 -0
  190. data/processor/command/show_subcmd/version.rb +23 -0
  191. data/processor/command/source.rb +133 -0
  192. data/processor/command/step.rb +97 -0
  193. data/processor/command/tbreak.rb +20 -0
  194. data/processor/command/unalias.rb +49 -0
  195. data/processor/command/undisplay.rb +63 -0
  196. data/processor/command/up.rb +89 -0
  197. data/processor/command.rb +173 -0
  198. data/processor/default.rb +64 -0
  199. data/processor/disassemble.rb +59 -0
  200. data/processor/display.rb +53 -0
  201. data/processor/eval.rb +97 -0
  202. data/processor/eventbuf.rb +101 -0
  203. data/processor/frame.rb +265 -0
  204. data/processor/help.rb +94 -0
  205. data/processor/hook.rb +134 -0
  206. data/processor/list.rb +123 -0
  207. data/processor/load_cmds.rb +253 -0
  208. data/processor/location.rb +228 -0
  209. data/processor/mock.rb +138 -0
  210. data/processor/msg.rb +74 -0
  211. data/processor/running.rb +244 -0
  212. data/processor/stepping.rb +135 -0
  213. data/processor/subcmd.rb +136 -0
  214. data/processor/validate.rb +379 -0
  215. data/processor/virtual.rb +33 -0
  216. data/processor.rb +404 -0
  217. data/rbx-trepanning.gemspec +39 -0
  218. data/sample/.gitignore +2 -0
  219. data/sample/list-terminal-colors.rb +139 -0
  220. data/sample/rocky-dot-trepanxrc +14 -0
  221. data/sample/rocky-trepanx-colors.rb +46 -0
  222. data/test/data/.gitignore +1 -0
  223. data/test/data/enable.right +36 -0
  224. data/test/data/fname-with-blank.cmd +6 -0
  225. data/test/data/fname-with-blank.right +6 -0
  226. data/test/data/inline-call.cmd +6 -0
  227. data/test/data/inline-call.right +14 -0
  228. data/test/data/quit-Xdebug.right +3 -0
  229. data/test/data/quit.cmd +5 -0
  230. data/test/data/quit.right +3 -0
  231. data/test/data/quit2.cmd +6 -0
  232. data/test/data/quit2.right +3 -0
  233. data/test/example/.gitignore +2 -0
  234. data/test/example/debugger-stop.rb +16 -0
  235. data/test/example/factorial.rb +10 -0
  236. data/test/example/fname with blank.rb +1 -0
  237. data/test/example/gcd-server.rb +22 -0
  238. data/test/example/gcd.rb +19 -0
  239. data/test/example/goto2goto.rb +11 -0
  240. data/test/example/inline-call.rb +23 -0
  241. data/test/example/null.rb +1 -0
  242. data/test/example/thread1.rb +3 -0
  243. data/test/functional/.gitignore +3 -0
  244. data/test/functional/fn_helper.rb +112 -0
  245. data/test/functional/test-break-name.rb +52 -0
  246. data/test/functional/test-break.rb +85 -0
  247. data/test/functional/test-eval.rb +115 -0
  248. data/test/functional/test-finish.rb +70 -0
  249. data/test/functional/test-fn_helper.rb +43 -0
  250. data/test/functional/test-list.rb +56 -0
  251. data/test/functional/test-next-bug.rb +49 -0
  252. data/test/functional/test-next.rb +101 -0
  253. data/test/functional/test-recursive-bt.rb +94 -0
  254. data/test/functional/test-step.rb +272 -0
  255. data/test/functional/test-step2.rb +35 -0
  256. data/test/functional/test-tbreak.rb +41 -0
  257. data/test/integration/.gitignore +3 -0
  258. data/test/integration/file-diff.rb +89 -0
  259. data/test/integration/helper.rb +81 -0
  260. data/test/integration/test-fname-with-blank.rb +16 -0
  261. data/test/integration/test-inline-call.rb +20 -0
  262. data/test/integration/test-quit.rb +47 -0
  263. data/test/unit/.gitignore +3 -0
  264. data/test/unit/cmd-helper.rb +50 -0
  265. data/test/unit/mock-helper.rb +10 -0
  266. data/test/unit/test-app-brkpt.rb +31 -0
  267. data/test/unit/test-app-brkptmgr.rb +51 -0
  268. data/test/unit/test-app-cmd_parse.rb +97 -0
  269. data/test/unit/test-app-cmd_parser.rb +23 -0
  270. data/test/unit/test-app-complete.rb +39 -0
  271. data/test/unit/test-app-condition.rb +18 -0
  272. data/test/unit/test-app-display.rb +22 -0
  273. data/test/unit/test-app-iseq.rb +64 -0
  274. data/test/unit/test-app-method.rb +54 -0
  275. data/test/unit/test-app-options.rb +94 -0
  276. data/test/unit/test-app-run.rb +14 -0
  277. data/test/unit/test-app-util.rb +44 -0
  278. data/test/unit/test-app-validate.rb +18 -0
  279. data/test/unit/test-base-cmd.rb +45 -0
  280. data/test/unit/test-base-subcmd.rb +57 -0
  281. data/test/unit/test-base-submgr.rb +24 -0
  282. data/test/unit/test-base-subsubcmd.rb +17 -0
  283. data/test/unit/test-bin-trepanx.rb +48 -0
  284. data/test/unit/test-cmd-alias.rb +48 -0
  285. data/test/unit/test-cmd-break.rb +66 -0
  286. data/test/unit/test-cmd-edit.rb +34 -0
  287. data/test/unit/test-cmd-exit.rb +27 -0
  288. data/test/unit/test-cmd-finish.rb +31 -0
  289. data/test/unit/test-cmd-help.rb +104 -0
  290. data/test/unit/test-cmd-kill.rb +54 -0
  291. data/test/unit/test-cmd-parse_list_cmd.rb +36 -0
  292. data/test/unit/test-cmd-source.rb +34 -0
  293. data/test/unit/test-cmd-step.rb +29 -0
  294. data/test/unit/test-command.rb +45 -0
  295. data/test/unit/test-completion.rb +48 -0
  296. data/test/unit/test-intf-user.rb +46 -0
  297. data/test/unit/test-io-input.rb +27 -0
  298. data/test/unit/test-io-tcp.rb +33 -0
  299. data/test/unit/test-io-tcpclient.rb +54 -0
  300. data/test/unit/test-io-tcpfns.rb +17 -0
  301. data/test/unit/test-io-tcpserver.rb +50 -0
  302. data/test/unit/test-proc-eval.rb +35 -0
  303. data/test/unit/test-proc-frame.rb +81 -0
  304. data/test/unit/test-proc-help.rb +16 -0
  305. data/test/unit/test-proc-hook.rb +30 -0
  306. data/test/unit/test-proc-list.rb +55 -0
  307. data/test/unit/test-proc-load_cmds.rb +51 -0
  308. data/test/unit/test-proc-location.rb +67 -0
  309. data/test/unit/test-proc-main.rb +95 -0
  310. data/test/unit/test-proc-validate.rb +139 -0
  311. data/test/unit/test-subcmd-help.rb +43 -0
  312. metadata +545 -0
data/app/brkptmgr.rb ADDED
@@ -0,0 +1,153 @@
1
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require 'set'
3
+ require 'rubygems'; require 'require_relative'
4
+ require_relative 'breakpoint'
5
+ class Trepan
6
+ class BreakpointMgr
7
+
8
+ attr_reader :list
9
+ attr_reader :set
10
+
11
+ def initialize
12
+ clear
13
+ end
14
+
15
+ def clear
16
+ @list = []
17
+ @set = Set.new
18
+ end
19
+
20
+ # Remove all breakpoints that we have recorded
21
+ def finalize
22
+ @list.each do |bp|
23
+ bp.related_bp.each { |bp| bp.remove! }
24
+ bp.remove!
25
+ end
26
+ clear
27
+ end
28
+
29
+ def <<(brkpt)
30
+ @list << brkpt
31
+ @set.add(set_key(brkpt))
32
+ end
33
+
34
+ def [](index)
35
+ raise TypeError,
36
+ "index #{index} should be a Fixnum, is #{index.class}" unless
37
+ index.is_a?(Fixnum)
38
+ @list.detect {|bp| bp.id == index }
39
+ end
40
+
41
+ alias detect []
42
+
43
+ def delete(index)
44
+ bp = detect(index)
45
+ if bp
46
+ delete_by_brkpt(bp)
47
+ return bp
48
+ else
49
+ return nil
50
+ end
51
+ end
52
+
53
+ def delete_by_brkpt(delete_bp)
54
+ @list = @list.reject{|candidate| candidate == delete_bp}
55
+ @set = Set.new(@list.map{|bp| set_key(bp)})
56
+ delete_bp.remove! unless @set.member?(set_key(delete_bp))
57
+ return delete_bp
58
+ end
59
+
60
+ def add(*args)
61
+ brkpt = Trepan::Breakpoint.new(*args)
62
+ @list << brkpt
63
+ @set.add(set_key(brkpt))
64
+ return brkpt
65
+ end
66
+
67
+ def empty?
68
+ @list.empty?
69
+ end
70
+
71
+ def line_breaks(cm)
72
+ result = {}
73
+ @list.each do |bp|
74
+ if bp.method == cm
75
+ result[bp.line] = bp
76
+ end
77
+ end
78
+ result
79
+ end
80
+
81
+ def find(meth, ip)
82
+ @list.detect do |bp|
83
+ if bp.enabled? && bp.ip == ip
84
+ begin
85
+ return bp ## if bp.condition?(bind)
86
+ rescue
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ def max
93
+ @list.map{|bp| bp.id}.max || 0
94
+ end
95
+
96
+ # Key used in @set to list unique instruction-sequence offsets.
97
+ def set_key(bp)
98
+ [bp.method, bp.ip]
99
+ end
100
+
101
+ def size
102
+ @list.size
103
+ end
104
+
105
+ def reset
106
+ @list.each{|bp| bp.remove!}
107
+ @list = []
108
+ @set = Set.new
109
+ end
110
+
111
+ end
112
+ end
113
+ if __FILE__ == $0
114
+ def bp_status(brkpts, i)
115
+ puts "list size: #{brkpts.list.size}"
116
+ puts "set size: #{brkpts.set.size}"
117
+ puts "max: #{brkpts.max}"
118
+ p brkpts
119
+ puts "--- #{i} ---"
120
+ end
121
+
122
+ meth = Rubinius::CompiledMethod.of_sender
123
+
124
+ brkpts = Trepan::BreakpointMgr.new
125
+ ObjectSpace.define_finalizer(brkpts, Proc.new {|arg| brkpts.finalize })
126
+ brkpts.add("<start>", meth, 0, 0, 1)
127
+ p brkpts[2]
128
+ bp_status(brkpts, 1)
129
+ # offset = frame.pc_offset
130
+ b2 = Trepan::Breakpoint.new("<2nd one>", meth, 0, 5, 2)
131
+ brkpts << b2
132
+ p brkpts.find(b2.method, b2.ip)
133
+ p brkpts[2]
134
+ puts '--- 2 ---'
135
+ ## p brkpts.line_breaks(iseq.source_container)
136
+ p brkpts.delete(2)
137
+ p brkpts[2]
138
+ bp_status(brkpts, 3)
139
+
140
+ # Two of the same breakpoints but delete 1 and see that the
141
+ # other still stays
142
+ b2 = Trepan::Breakpoint.new("<dup brkpt>", meth, 0, 0, 0)
143
+ brkpts << b2
144
+ bp_status(brkpts, 4)
145
+ b3 = Trepan::Breakpoint.new("<dup brkpt>", meth, 0, 0, 0)
146
+ brkpts << b3
147
+ bp_status(brkpts, 5)
148
+ brkpts.delete_by_brkpt(b2)
149
+ bp_status(brkpts, 6)
150
+ brkpts.delete_by_brkpt(b3)
151
+ bp_status(brkpts, 7)
152
+ brkpts.finalize
153
+ end
data/app/client.rb ADDED
@@ -0,0 +1,71 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2011, 2012 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require 'rubygems'; require 'require_relative'
4
+ require_relative 'default' # default debugger settings
5
+ require_relative '../lib/trepanning' # main Trepan object & initialization
6
+ require_relative '../interface/comcodes' # communication codes
7
+
8
+ module Trepanning
9
+ include Trepanning::RemoteCommunication
10
+ def start_client(options)
11
+ puts "Client option given"
12
+ user_opts = {}
13
+ %w(readline).each do |opt|
14
+ user_opts[opt.to_sym] = options[opt.to_sym]
15
+ end
16
+ dbgr = Trepan.new(:client => true,
17
+ :cmdfiles => [],
18
+ :initial_dir => options[:chdir],
19
+ :nx => true,
20
+ :host => options[:host],
21
+ :port => options[:port],
22
+ :user_opts => user_opts
23
+ )
24
+ intf = dbgr.intf[-1]
25
+ while true
26
+ begin
27
+ control_code, line = intf.read_remote
28
+ rescue EOFError, Errno::EPIPE
29
+ puts "Remote debugged process closed connection"
30
+ break
31
+ end
32
+ # p [control_code, line]
33
+ case control_code
34
+ when PRINT
35
+
36
+ # FIXME: don't know why server sometimes adds a gratuituous space.
37
+ # the space is added somewhere inside TCPSocket.print
38
+ line = line[0..-2] if line.end_with?("\n ")
39
+
40
+ print line
41
+ when CONFIRM_TRUE
42
+ response = intf.confirm(line, true)
43
+ intf.write_remote(CONFIRM_REPLY, response ? 'Y' : 'N')
44
+ when CONFIRM_FALSE
45
+ response = intf.confirm(line, true)
46
+ intf.write_remote(CONFIRM_REPLY, response ? 'Y' : 'N')
47
+ when PROMPT
48
+ # Printing of prompt has been handled already by PRINT.
49
+ begin
50
+ command = intf.read_command(line)
51
+ rescue EOFError
52
+ puts "user-side EOF. Quitting..."
53
+ break
54
+ end
55
+ begin
56
+ intf.write_remote(COMMAND, command)
57
+ rescue Errno::EPIPE
58
+ puts "Remote debugged process died"
59
+ break
60
+ end
61
+ when QUIT
62
+ break
63
+ when RESTART
64
+ break
65
+ else
66
+ $stderr.puts "** Unknown control code: #{control_code}"
67
+ end
68
+ end
69
+ end
70
+ module_function :start_client
71
+ end
@@ -0,0 +1,242 @@
1
+ # -*- Ruby -*-
2
+
3
+ %% {
4
+ #####################################################
5
+ # Structure to hold composite method names
6
+ SymbolEntry = Struct.new(:type, :name, :chain)
7
+
8
+
9
+ # Structure to hold position information
10
+ Position = Struct.new(:container_type, :container,
11
+ :position_type, :position)
12
+
13
+ # Structure to hold breakpoint information
14
+ Breakpoint = Struct.new(:position, :negate, :condition)
15
+
16
+ # Structure to hold list information
17
+ List = Struct.new(:position, :num)
18
+
19
+ DEFAULT_OPTS = {
20
+ :debug=>false,
21
+ :file_exists_proc => Proc.new{|filename|
22
+ File.readable?(filename) && !File.directory?(filename)
23
+ }
24
+ }
25
+ def initialize(str, opts={})
26
+ @opts = DEFAULT_OPTS.merge(opts)
27
+ setup_parser(str, opts[:debug])
28
+ @file_exists_proc = @opts[:file_exists_proc]
29
+ end
30
+
31
+
32
+ }
33
+ #####################################################
34
+
35
+ upcase_letter = /[A-Z]/
36
+ downcase_letter = /[a-z]/
37
+ suffix_letter = /[=!?]/
38
+ letter = upcase_letter
39
+ | downcase_letter
40
+ id_symbol = letter | "_" | [0-9]
41
+
42
+
43
+ # An variable or a method identifier
44
+ # Examples:
45
+ # var1
46
+ # my_var?
47
+ # But not: Variable or @var
48
+ vm_identifier = < (downcase_letter | "_") id_symbol* suffix_letter? >
49
+ {
50
+ SymbolEntry.new(:variable, text)
51
+ }
52
+
53
+ # Examples:
54
+ # var1
55
+ # But not: my_var?, my_var!
56
+ variable_identifier = < (downcase_letter | "_") id_symbol* >
57
+ {
58
+ SymbolEntry.new(:variable, text)
59
+ }
60
+
61
+ # Examples:
62
+ # MY_CONSTANT
63
+ # MyConstant_01
64
+ # But not:
65
+ # MyConstant_01?
66
+ constant_identifier = < upcase_letter id_symbol* >
67
+ {
68
+ SymbolEntry.new(:constant, text)
69
+ }
70
+
71
+ # Examples:
72
+ # $global_variable
73
+ # We won't try for funny global names like $$, $? $:, $', etc
74
+ global_identifier = < "$" (constant_identifier | variable_identifier) >
75
+ {
76
+ SymbolEntry.new(:global, text)
77
+ }
78
+
79
+ # Examples:
80
+ # Foo
81
+ # foo
82
+ # But not:
83
+ # foo!, @foo, Class.foo
84
+ local_internal_identifier = constant_identifier | variable_identifier
85
+
86
+ # Examples:
87
+ # Foo, foo, foo!
88
+ # foo
89
+ # But not:
90
+ # @foo, Class.foo
91
+ local_identifier = constant_identifier | vm_identifier
92
+
93
+ # Example: @foo
94
+ instance_identifier = < '@' local_identifier >
95
+ {
96
+ SymbolEntry.new(:instance, text)
97
+ }
98
+
99
+
100
+ # Example: @@foo
101
+ classvar_identifier = ('@@' local_identifier:id )
102
+ {
103
+ SymbolEntry.new(:classvar, id)
104
+ }
105
+
106
+ identifier = global_identifier
107
+ | instance_identifier
108
+ | classvar_identifier
109
+ | local_identifier
110
+
111
+ id_separator = < '::'|'.' > { text }
112
+
113
+ # Like of class_module_chain *after* the first name. So we don't
114
+ # allow sigils in the initial id. That is we don't allow:
115
+ # Class.@name1.@@name2.$name3
116
+ # But we do allow final sigils:
117
+ # class.name!, class.name=
118
+ internal_class_module_chain =
119
+ < local_internal_identifier:parent id_separator:sep
120
+ internal_class_module_chain:child >
121
+ {
122
+ SymbolEntry.new(parent.type, text, [parent, child, sep])
123
+ }
124
+ | local_identifier
125
+
126
+
127
+ # I think strict Ruby rules are that once one goes from :: to .
128
+ # There is no going back. That is, A.B::C is invalid.
129
+ #
130
+ # Also I think method names can't be constants. But such
131
+ # subtleties we'll handle when we process the final structure.
132
+ # Examples:
133
+ # Object, A::B, A.b @@foo.bar, $foo.bar.baz?
134
+
135
+ class_module_chain =
136
+ < identifier:parent id_separator:sep internal_class_module_chain:child >
137
+ {
138
+ SymbolEntry.new(parent.type, text, [parent, child, sep])
139
+ }
140
+ | identifier
141
+
142
+ ##############################################################
143
+ # Location-specific things. This is used in conjunction with
144
+ # method-like things above.
145
+ sp = /[ \t]/
146
+ - = sp+
147
+ dbl_escapes = "\\\"" { '"' }
148
+ | "\\n" { "\n" }
149
+ | "\\t" { "\t" }
150
+ | "\\\\" { "\\" }
151
+ escapes = "\\\"" { '"' }
152
+ | "\\n" { "\n" }
153
+ | "\\t" { "\t" }
154
+ | "\\ " { " " }
155
+ | "\\:" { ":" }
156
+ | "\\\\" { "\\" }
157
+ dbl_seq = < /[^\\"]+/ > { text }
158
+ dbl_not_quote = (dbl_escapes | dbl_seq)+:ary { ary }
159
+ dbl_string = "\"" dbl_not_quote:ary "\"" { ary.join }
160
+ not_space_colon = escapes
161
+ | < /[^ \t\n:]/ > { text }
162
+ not_space_colons = ( not_space_colon )+:ary { ary.join }
163
+ filename = dbl_string | not_space_colons
164
+ file_pos_sep = sp+ | ':'
165
+ integer = </[0-9]+/> { text.to_i }
166
+ sinteger = </[+-]?[0-9]+/> { text.to_i }
167
+ line_number = integer
168
+
169
+ vm_offset = '@' integer:int
170
+ {
171
+ Position.new(nil, nil, :offset, int)
172
+ }
173
+
174
+ # Examples:
175
+ # @43
176
+ # 5
177
+ position =
178
+ vm_offset
179
+ | line_number:l {
180
+ Position.new(nil, nil, :line, l)
181
+ }
182
+
183
+ file_colon_line = file_no_colon:file &{ File.exist?(file) } ':' position:pos {
184
+ Position.new(:file, file, pos.position_type, pos.position)
185
+ }
186
+
187
+ # Examples:
188
+ # Myclass.fn @5 # bytecode offset 5 of fn
189
+ # Myclass.fn:@5 # same as above
190
+ # Myclass.fn 5 # line number 5 of fn
191
+ # Note: Myclass.fn could be either a filename or a method name
192
+
193
+ # The below ordering is important.
194
+ # 1. Numbers can't be method names they are first. If there's a
195
+ # file with that name, later we'll allow quoting to indicate filename.
196
+ # 2. filename:position can't also be a method so that's next
197
+ # 3. It is possible a filename can be a method name, but we
198
+ # test using File.exist? so we want to put this first.
199
+ # Later "quoting" will skip the File.exist?
200
+ # 4. Class module *with* a position is next and has to be before
201
+ # without a position, else we would stop early before handling
202
+ # the position.
203
+
204
+ location =
205
+ position
206
+ | <filename>:file &{ @file_exists_proc.call(file) } file_pos_sep position:pos {
207
+ Position.new(:file, file, pos.position_type, pos.position)
208
+ }
209
+ | <filename>:file &{ @file_exists_proc.call(file) } {
210
+ Position.new(:file, file, nil, nil)
211
+ }
212
+ | class_module_chain?:fn file_pos_sep position:pos {
213
+ Position.new(:fn, fn, pos.position_type, pos.position)
214
+ }
215
+ | class_module_chain?:fn {
216
+ Position.new(:fn, fn, nil, nil)
217
+ }
218
+
219
+ if_unless = <"if" | "unless"> { text }
220
+ condition = </.+/> { text}
221
+
222
+ breakpoint_stmt_no_condition = location:loc {
223
+ Breakpoint.new(loc, false, 'true')
224
+ }
225
+
226
+ # Note that the first word "break" is handled in the command.
227
+ # Also, "break" with nothing else is handled there as well
228
+ breakpoint_stmt = location:loc - if_unless:iu - condition:cond {
229
+ Breakpoint.new(loc, iu == 'unless', cond)
230
+ }
231
+ | breakpoint_stmt_no_condition
232
+
233
+ # Note that the first word "list", "list>" or handled in
234
+ # the command. Also, "list" with nothing else is
235
+ # handled there as well
236
+ list_special_targets = <'.' | '-'> { text }
237
+ list_stmt = (list_special_targets | location):loc - (sinteger:int)? {
238
+ List.new(loc, int)
239
+ }
240
+ | (list_special_targets | location):loc {
241
+ List.new(loc, nil)
242
+ }
data/app/cmd_parse.rb ADDED
@@ -0,0 +1,209 @@
1
+ # use_grammar.rb
2
+ require 'rubygems'
3
+ require 'require_relative'
4
+ require_relative 'cmd_parser'
5
+
6
+ class Trepan
7
+ module CmdParser
8
+
9
+ # Given a KPeg parse object, return the method of that parse or raise a
10
+ # Name error if we can't find a method. parent_class is the parent class of
11
+ # the object we've found so far and "binding" is used if we need
12
+ # to use eval to find the method.
13
+ def resolve_method(m, bind, parent_class = nil)
14
+ name = m.name
15
+ # DEBUG p name
16
+ errmsg = nil
17
+ if m.type == :constant
18
+ begin
19
+ if parent_class
20
+ klass = parent_class.const_get(m.chain[0].name)
21
+ else
22
+ errmsg = "Constant #{m} is not a class or module"
23
+ raise NameError, errmsg unless m.chain[0]
24
+ klass = eval(m.chain[0].name, bind)
25
+ end
26
+ errmsg = "Constant #{klass} is not a class or module" unless
27
+ raise NameError, errmsg unless
28
+ klass.kind_of?(Class) or klass.kind_of?(Module)
29
+ m = m.chain[1]
30
+ if klass.instance_methods.member?('binding')
31
+ bind = klass.bind
32
+ elsif klass.private_instance_methods.member?('binding')
33
+ bind = klass.send(:binding)
34
+ else
35
+ bind = nil
36
+ end
37
+ resolve_method(m, bind, klass)
38
+ rescue NameError
39
+ errmsg ||= "Can't resolve constant #{name}"
40
+ raise NameError, errmsg
41
+ end
42
+ else
43
+ is_class =
44
+ begin
45
+ m.chain && m.chain[0] &&
46
+ Class == eval("#{m.chain[0].name}.class", bind)
47
+ rescue
48
+ false
49
+ end
50
+ if is_class
51
+ # Handles stuff like:
52
+ # x = File
53
+ # x.basename
54
+ # Above, we tested we get a class back when we evalate m.chain[0]
55
+ # below. So it is safe to run the eval.
56
+ klass = eval("#{m.chain[0].name}", bind)
57
+ resolve_method(m.chain[1], klass.send(:binding), klass)
58
+ else
59
+ begin
60
+ errmsg = "Can't get method for #{name.inspect}"
61
+ if m.chain && m.chain[0]
62
+ parent_obj = eval("#{m.chain[0].name}", bind) if !parent_class && bind
63
+ end
64
+ parent = parent_class || parent_obj
65
+ meth =
66
+ if parent
67
+ errmsg << "in #{parent}"
68
+ lookup_name = m.chain && m.chain[1] ? m.chain[1].name : name
69
+ if parent.respond_to?('instance_methods') &&
70
+ parent.instance_methods.member?(lookup_name)
71
+ parent.instance_method(lookup_name)
72
+ elsif parent.respond_to?('methods')
73
+ parent.method(lookup_name)
74
+ end
75
+ elsif m.chain && m.chain[1]
76
+ eval("#{m.chain[0].name}.method(#{lookup_name.name.inspect})", bind)
77
+ else
78
+ eval("self.method(#{name.inspect})", bind)
79
+ end
80
+ return meth
81
+ rescue
82
+ raise NameError, errmsg
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ # Return the method by evaluating parse_struct.
89
+ # nil is returned if we can't parse str
90
+ def meth_for_parse_struct(parse_struct, start_binding)
91
+ resolve_method(parse_struct, start_binding)
92
+ end
93
+
94
+ # Parse str and return the method associated with that.
95
+ # nil is returned if we can't parse str
96
+ def meth_for_string(str, start_binding)
97
+ @cp ? @cp.setup_parser(str) : @cp = CmdParse.new(str)
98
+ begin
99
+ if @cp._class_module_chain
100
+ # Did we match all of it?
101
+ if @cp.result.name == str.strip
102
+ meth_for_parse_struct(@cp.result, start_binding)
103
+ else
104
+ nil
105
+ end
106
+ else
107
+ # FIXME: change to raise ParseError?
108
+ nil
109
+ end
110
+ rescue NameError
111
+ return nil
112
+ end
113
+ end
114
+
115
+ def parse_terminal(terminal_name, loc_str, opts={})
116
+ @cp ? @cp.setup_parser(loc_str) : @cp = CmdParse.new(loc_str, opts)
117
+ @cp.send(terminal_name) ? @cp : nil
118
+ end
119
+
120
+ def parse_location(loc_str, opts={})
121
+ parse = parse_terminal(:_location, loc_str, opts)
122
+ parse ? parse.result : nil
123
+ end
124
+
125
+ def parse_breakpoint(str, opts={})
126
+ parse = parse_terminal(:_breakpoint_stmt, str, opts)
127
+ parse ? parse.result : nil
128
+ end
129
+
130
+ def parse_breakpoint_no_condition(str, opts={})
131
+ parse = parse_terminal(:_breakpoint_stmt_no_condition, str, opts)
132
+ parse ? parse.result : nil
133
+ end
134
+
135
+ def parse_list(str, opts={})
136
+ parse = parse_terminal(:_list_stmt, str, opts)
137
+ parse ? parse.result : nil
138
+ end
139
+ end
140
+ end
141
+
142
+ if __FILE__ == $0
143
+ # Demo it.
144
+ %w(a a1 $global __FILE__ Constant 0 1e10 a.b).each do |name|
145
+ cp = CmdParse.new(name)
146
+ if cp._identifier && cp.result.name == name
147
+ p [cp.string, cp.result, 'succeeded']
148
+ else
149
+ puts "#{name} failed"
150
+ end
151
+ end
152
+
153
+ %w(Object A::B A::B::C A::B::C::D A::B.c A.b.c.d A(5)
154
+ Rubinius::VariableScope::method_visibility
155
+ ).each do |name|
156
+ cp = CmdParse.new(name)
157
+ if cp._class_module_chain && cp.result.name == name
158
+ p [cp.string, cp.result, 'succeeded']
159
+ else
160
+ puts "#{name} failed"
161
+ end
162
+ end
163
+
164
+ def five; 5 end
165
+ include Trepan::CmdParser
166
+ p meth_for_string('Array.map', binding)
167
+ p meth_for_string('Rubinius::VM.backtrace', binding)
168
+ %w(five
169
+ Array.map
170
+ Rubinius::VM.backtrace
171
+ Kernel.eval
172
+ Kernel::eval).each do |str|
173
+ meth = meth_for_string(str, binding)
174
+ p meth
175
+ end
176
+ module Testing
177
+ def testing; 5 end
178
+ module_function :testing
179
+ end
180
+ p meth_for_string('Testing.testing', binding)
181
+ p meth_for_string('File.basename', binding)
182
+ x = File
183
+ # require_relative '../lib/trepanning'
184
+ # debugger
185
+ p meth_for_string('x.basename', binding)
186
+ def x.five; 5; end
187
+ p meth_for_string('x.five', binding)
188
+ p x.five
189
+
190
+ p parse_terminal(:_line_number, '5').result
191
+ p parse_terminal(:_vm_offset, '@5').result
192
+
193
+ # Location stuff
194
+ ['fn', 'fn 5', 'fn @5', '@5', '5',
195
+ '../test/example/test\ fname\ with\ blank.rb'].each do |location|
196
+ p parse_location(location)
197
+ end
198
+
199
+ # require_relative '../lib/trepanning'; debugger
200
+ # parse_location('../test/example/test\ fname\ with\ blank.rb')
201
+
202
+ # Location stuff
203
+ ['fn if a > b', 'fn 5 unless c > d', 'fn:5 if x', '@5', '5'].each do |str|
204
+ p parse_breakpoint(str)
205
+ end
206
+
207
+
208
+ end
209
+