rbx-trepanning 0.2.0-universal-rubinius-2.0

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 (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/processor/list.rb ADDED
@@ -0,0 +1,123 @@
1
+ # Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+
3
+ # Trepan command list validation routines. A String type is
4
+ # usually passed in as the argument to validation routines.
5
+
6
+ require 'rubygems'
7
+ require 'require_relative'
8
+
9
+ require_relative './validate'
10
+
11
+ class Trepan
12
+ class CmdProcessor < VirtualCmdProcessor
13
+
14
+ # If last is less than first, assume last is a count rather than an
15
+ # end line number. If last is negative, range is [first+last..first].
16
+ def adjust_last(first, last)
17
+ last < first ? first + last - 1 : last
18
+ end
19
+
20
+ # Parse a list command. On success return:
21
+ # - compiled method
22
+ # - the line number - a Fixnum
23
+ # - file name
24
+ # - last line
25
+ def parse_list_cmd(position_str, listsize, center_correction=0)
26
+ cm = nil
27
+ if position_str.empty?
28
+ filename = frame.file
29
+ first = [1, frame.line - center_correction].max
30
+ else
31
+ list_cmd_parse = parse_list(position_str,
32
+ :file_exists_proc => file_exists_proc)
33
+ return [nil] * 4 unless list_cmd_parse
34
+ last = list_cmd_parse.num
35
+ position = list_cmd_parse.position
36
+
37
+ if position.is_a?(String)
38
+ if position == '-'
39
+ return no_frame_msg_for_list unless frame.line
40
+ first = [1, frame.line - 2*listsize - 1].max
41
+ elsif position == '.'
42
+ return no_frame_msg_for_list unless frame.line
43
+ if (second = list_cmd_parse.num)
44
+ first = frame.line
45
+ last = adjust_last(first, second)
46
+ else
47
+ first = [1, frame.line - center_correction].max
48
+ last = first + listsize - 1
49
+ end
50
+ end
51
+ filename = frame.file
52
+ cm = frame.method
53
+ else
54
+ cm, filename, offset, offset_type =
55
+ parse_position(position)
56
+
57
+ return [nil] * 4 unless filename
58
+ if offset_type == :line
59
+ first = offset
60
+ elsif cm
61
+ first, vm_offset =
62
+ position_to_line_and_offset(cm, filename, position,
63
+ offset_type)
64
+ unless first
65
+ errmsg("Unable to get location in #{meth_or_frame}")
66
+ return [nil] * 4
67
+ end
68
+ elsif !offset
69
+ first = 1
70
+ else
71
+ errmsg("Unable to parse list position #{position_str}")
72
+ return [nil] * 4
73
+ end
74
+ end
75
+ end
76
+ if last
77
+ first, last = [first + last, first] if last < 0
78
+ last = adjust_last(first, last)
79
+ else
80
+ first = [1, first - center_correction].max
81
+ last = first + listsize - 1 unless last
82
+ end
83
+ LineCache::cache(filename) unless LineCache::cached?(filename)
84
+ return [cm, filename, first, last]
85
+ end
86
+
87
+ def no_frame_msg_for_list
88
+ errmsg("No Ruby program loaded.")
89
+ return [nil] * 4
90
+ end
91
+
92
+ end
93
+ end
94
+
95
+ if __FILE__ == $0
96
+ # Demo it.
97
+ require_relative 'mock'
98
+ require_relative 'frame'
99
+ dbgr, cmd = MockDebugger::setup('exit', false)
100
+ cmdproc = cmd.proc
101
+ cmdproc.frame_initialize
102
+ cmdproc.instance_variable_set('@settings',
103
+ Trepan::CmdProcessor::DEFAULT_SETTINGS)
104
+ def foo; 5 end
105
+ def cmdproc.errmsg(msg)
106
+ puts msg
107
+ end
108
+ puts '-' * 20
109
+ p cmdproc.parse_list_cmd('.', 10)
110
+ p cmdproc.parse_list_cmd('-', 10)
111
+ p cmdproc.parse_list_cmd('foo', 10)
112
+ p cmdproc.parse_list_cmd('@0', 10)
113
+ p cmdproc.parse_list_cmd("#{__LINE__}", 10)
114
+ p cmdproc.parse_list_cmd("#{__FILE__} @0", 10)
115
+ p '-' * 40
116
+ # require_relative '../lib/trepanning'; debugger
117
+ p cmdproc.parse_list_cmd("#{__FILE__}:#{__LINE__}", 10)
118
+ p cmdproc.parse_list_cmd("#{__FILE__} #{__LINE__}", 10)
119
+ p '-' * 40
120
+ p cmdproc.parse_list_cmd("cmdproc.errmsg", 10)
121
+ p cmdproc.parse_list_cmd("cmdproc.errmsg:@0", 10)
122
+ p cmdproc.parse_list_cmd("cmdproc.errmsg:@0", -10)
123
+ end
@@ -0,0 +1,253 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require 'tmpdir'
4
+
5
+ # Part of Trepan::CmdProcess that loads up debugger commands from
6
+ # builtin and user directories.
7
+ # Sets @commands, @aliases, @macros
8
+ require 'rubygems'; require 'require_relative'
9
+ require_relative '../app/complete'
10
+ require_relative 'virtual'
11
+ class Trepan
12
+ class CmdProcessor < VirtualCmdProcessor
13
+
14
+ attr_reader :aliases # Hash[String] of command names
15
+ # indexed by alias name
16
+ attr_reader :commands # Hash[String] of command objects
17
+ # indexed by name
18
+ attr_reader :macros # Hash[String] of Proc objects
19
+ # indexed by macro name.
20
+ attr_reader :leading_str # leading part of string. Used in
21
+ # command completion
22
+
23
+ # "initialize" for multi-file class. Called from main.rb's "initialize".
24
+ def load_cmds_initialize
25
+ @commands = {}
26
+ @aliases = {}
27
+ @macros = {}
28
+
29
+ cmd_dirs = [ File.join(File.dirname(__FILE__), 'command') ]
30
+ cmd_dirs << @settings[:user_cmd_dir] if @settings[:user_cmd_dir]
31
+ cmd_dirs.each do |cmd_dir|
32
+ load_debugger_commands(cmd_dir) if File.directory?(cmd_dir)
33
+ end
34
+ end
35
+
36
+ # Loads in debugger commands by require'ing each ruby file in the
37
+ # 'command' directory. Then a new instance of each class of the
38
+ # form Trepan::xxCommand is added to @commands and that array
39
+ # is returned.
40
+ def load_debugger_commands(file_or_dir)
41
+ if File.directory?(file_or_dir)
42
+ dir = File.expand_path(file_or_dir)
43
+ # Change $0 so it doesn't get in the way of __FILE__ = $0.
44
+ # In rubinius 2.0.0.rc1 (1.8.7 93c75658...) $0 is nil
45
+ # and this can cause an error when one restores $0 below.
46
+ # See https://github.com/rubinius/rubinius/issues/2450
47
+ old_dollar0 = $0 || '' #
48
+ $0 = ''
49
+ Dir.glob(File.join(dir, '*.rb')).each do |rb|
50
+ # We use require so that multiple calls have no effect.
51
+ require rb
52
+ end
53
+ $0 = old_dollar0
54
+ elsif File.readable?(file_or_dir)
55
+ # We use load in case we are reloading.
56
+ # 'require' would not be effective here
57
+ load file_or_dir
58
+ else
59
+ return false
60
+ end
61
+ # Instantiate each Command class found by the above require(s).
62
+ Trepan::Command.constants.grep(/.Command$/).each do |name|
63
+ klass = Trepan::Command.const_get(name)
64
+ cmd = klass.send(:new, self)
65
+
66
+ # Add to list of commands and aliases.
67
+ cmd_name = klass.const_get(:NAME)
68
+ if klass.constants.member?('ALIASES')
69
+ aliases= klass.const_get('ALIASES')
70
+ aliases.each {|a| @aliases[a] = cmd_name}
71
+ end
72
+ @commands[cmd_name] = cmd
73
+ end
74
+ end
75
+
76
+ # Instantiate a Trepan::Command and extract info: the NAME, ALIASES
77
+ # and store the command in @commands.
78
+ def setup_command(command)
79
+ # Note: there is probably a non-eval way to instantiate the
80
+ # command, but I don't know it. And eval works.
81
+ klass = self.instance_eval("Trepan::Command::#{command}")
82
+ cmd = klass.send(:new, self)
83
+
84
+ # Add to list of commands and aliases.
85
+ cmd_name = klass.const_get(:NAME)
86
+ if klass.constants.member?(:ALIASES)
87
+ aliases= klass.const_get(:ALIASES)
88
+ aliases.each {|a| @aliases[a] = cmd_name}
89
+ end
90
+ @commands[cmd_name] = cmd
91
+ end
92
+
93
+ # Looks up cmd_array[0] in @commands and runs that. We do lots of
94
+ # validity testing on cmd_array.
95
+ def run_cmd(cmd_array)
96
+ unless cmd_array.is_a?(Array)
97
+ errmsg "run_cmd argument should be an Array, got: #{cmd_array.class}"
98
+ return
99
+ end
100
+ if cmd_array.detect{|item| !item.is_a?(String)}
101
+ errmsg "run_cmd argument Array should only contain strings. " +
102
+ "Got #{cmd_array.inspect}"
103
+ return
104
+ end
105
+ if cmd_array.empty?
106
+ errmsg "run_cmd Array should have at least one item. " +
107
+ "Got: #{cmd_array.inspect}"
108
+ return
109
+ end
110
+ cmd_name = cmd_array[0]
111
+ if @commands.member?(cmd_name)
112
+ @commands[cmd_name].run(cmd_array)
113
+ end
114
+ end
115
+
116
+ def save_commands(opts)
117
+ save_filename = opts[:filename] ||
118
+ File.join(Dir.tmpdir, "trepanning-save-#{$$}.txt")
119
+ begin
120
+ save_file = File.open(save_filename, 'w')
121
+ rescue => exc
122
+ errmsg("Can't open #{save_filename} for writing.")
123
+ errmsg("System reports: #{exc.inspect}")
124
+ return nil
125
+ end
126
+ save_file.puts "#\n# Commands to restore trepanning environment\n#\n"
127
+ @commands.each do |cmd_name, cmd_obj|
128
+ cmd_obj.save_command if cmd_obj.respond_to?(:save_command)
129
+ next unless cmd_obj.is_a?(Trepan::SubcommandMgr)
130
+ cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj|
131
+ save_file.puts subcmd_obj.save_command if
132
+ subcmd_obj.respond_to?(:save_command)
133
+ next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr)
134
+ subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj|
135
+ save_file.puts subsubcmd_obj.save_command if
136
+ subsubcmd_obj.respond_to?(:save_command)
137
+ end
138
+ end
139
+ end
140
+ save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
141
+ opts[:erase]
142
+ save_file.close
143
+
144
+ return save_filename
145
+ end
146
+
147
+ # Handle initial completion. We draw from the commands, aliases,
148
+ # and macros for completion. However we won't include aliases which
149
+ # are prefixes of other commands.
150
+ def complete(str, last_token)
151
+ @leading_str = str
152
+ next_blank_pos, token = Trepan::Complete.next_token(str, 0)
153
+ return [''] if token.empty? && !last_token.empty?
154
+ match_pairs = Trepan::Complete.complete_token_with_next(@commands,
155
+ token)
156
+ match_hash = {}
157
+ match_pairs.each do |pair|
158
+ match_hash[pair[0]] = pair[1]
159
+ end
160
+ alias_pairs = Trepan::Complete.
161
+ complete_token_filtered_with_next(@aliases, token, match_hash,
162
+ @commands)
163
+ match_pairs += alias_pairs
164
+ if str[next_blank_pos..-1].empty?
165
+ return match_pairs.map{|pair| pair[0]}.sort
166
+ else
167
+ alias_pairs.each do |pair|
168
+ match_hash[pair[0]] = pair[1]
169
+ end
170
+ end
171
+ if match_pairs.size > 1
172
+ # FIXME: figure out what to do here.
173
+ # Matched multiple items in the middle of the string
174
+ # We can't handle this so do nothing.
175
+ return []
176
+ # return match_pairs.map do |name, cmd|
177
+ # ["#{name} #{args[1..-1].join(' ')}"]
178
+ # end
179
+ end
180
+ # match_pairs.size <= 1
181
+ next_complete(str, next_blank_pos, match_pairs[0][1], last_token)
182
+ end
183
+
184
+ def next_complete(str, next_blank_pos, cmd, last_token)
185
+ next_blank_pos, token = Trepan::Complete.next_token(str, next_blank_pos)
186
+ return [] if token.empty? && !last_token.empty?
187
+
188
+ if cmd.respond_to?(:complete_token_with_next)
189
+ match_pairs = cmd.complete_token_with_next(token)
190
+ return [] if match_pairs.empty?
191
+ if str[next_blank_pos..-1].rstrip.empty? &&
192
+ (token.empty? || token == last_token)
193
+ return match_pairs.map { |completion, junk| completion }
194
+ else
195
+ if match_pairs.size == 1
196
+ return next_complete(str, next_blank_pos, match_pairs[0][1],
197
+ last_token)
198
+ else
199
+ # FIXME: figure out what to do here.
200
+ # Matched multiple items in the middle of the string
201
+ # We can't handle this so do nothing.
202
+ return []
203
+ end
204
+ end
205
+ elsif cmd.respond_to?(:complete)
206
+ matches = cmd.complete(token)
207
+ return [] if matches.empty?
208
+ if str[next_blank_pos..-1].rstrip.empty? &&
209
+ (token.empty? || token == last_token)
210
+ return matches
211
+ else
212
+ # FIXME: figure out what to do here.
213
+ # Matched multiple items in the middle of the string
214
+ # We can't handle this so do nothing.
215
+ return []
216
+ end
217
+ else
218
+ return []
219
+ end
220
+ end
221
+ end
222
+ end
223
+ if __FILE__ == $0
224
+ class Trepan::CmdProcessor
225
+ def initialize(core, settings={})
226
+ end
227
+ end
228
+
229
+ cmdproc = Trepan::CmdProcessor.new(nil)
230
+ cmddir = File.join(File.dirname(__FILE__), 'command')
231
+ cmdproc.instance_variable_set('@settings', {})
232
+ cmdproc.load_cmds_initialize
233
+ require 'columnize'
234
+ puts Columnize.columnize(cmdproc.commands.keys.sort)
235
+ puts '=' * 20
236
+ puts Columnize.columnize(cmdproc.aliases.keys.sort)
237
+ puts '=' * 20
238
+
239
+ def cmdproc.errmsg(mess)
240
+ puts "** #{mess}"
241
+ end
242
+
243
+ def cmdproc.msg(mess)
244
+ puts mess
245
+ end
246
+
247
+ cmdproc.run_cmd('foo') # Invalid - not an Array
248
+ cmdproc.run_cmd([]) # Invalid - empty Array
249
+ cmdproc.run_cmd(['list', 5]) # Invalid - nonstring arg
250
+ p cmdproc.complete("d", 'd')
251
+ p cmdproc.complete("sho d", 'd')
252
+ p cmdproc.complete('', '')
253
+ end
@@ -0,0 +1,228 @@
1
+ # Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require 'rubygems';
3
+ require 'pathname' # For cleanpath
4
+ require 'linecache'
5
+ require 'require_relative'
6
+ require_relative 'disassemble'
7
+ require_relative 'msg'
8
+ require_relative 'frame'
9
+ require_relative '../app/file'
10
+ require_relative 'virtual'
11
+ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
12
+
13
+ unless defined?(EVENT2ICON)
14
+ # Event icons used in printing locations.
15
+ EVENT2ICON = {
16
+ 'brkpt' => 'xx',
17
+ 'tbrkpt' => 'x1',
18
+ 'c-call' => 'C>',
19
+ 'c-return' => '<C',
20
+ 'step-call' => '->',
21
+ 'call' => '->',
22
+ 'class' => '::',
23
+ 'coverage' => '[]',
24
+ 'debugger-call' => ':o',
25
+ 'end' => '-|',
26
+ 'line' => '--',
27
+ 'raise' => '!!',
28
+ 'return' => '<-',
29
+ 'start' => '>>',
30
+ 'switch' => 'sw',
31
+ 'trace-var' => '$V',
32
+ 'unknown' => '?!',
33
+ 'vm' => 'VM',
34
+ 'vm-insn' => '..',
35
+ }
36
+ end
37
+
38
+ def canonic_file(filename, resolve=true)
39
+ # For now we want resolved filenames
40
+ if @settings[:basename]
41
+ return File.basename(filename)
42
+ end
43
+ if resolve
44
+ try_filename = LineCache::map_file(filename)
45
+ filename = try_filename || filename
46
+ if !File.exist?(filename)
47
+ if (try_filename = find_load_path(filename))
48
+ return try_filename
49
+ elsif (try_filename = resolve_file_with_dir(filename))
50
+ return try_filename
51
+ else
52
+ return File.expand_path(Pathname.new(filename).cleanpath.to_s).
53
+ gsub(/\.rbc$/, '.rb')
54
+ end
55
+ end
56
+ end
57
+ return filename.gsub(/\.rbc$/, '.rb')
58
+ end
59
+
60
+ # Return the text to the current source line.
61
+ # FIXME: loc_and_text should call this rather than the other
62
+ # way around.
63
+ def current_source_text
64
+ opts = {:reload_on_change => settings[:reload]}
65
+ loc, junk, text = loc_and_text(source_location_info, opts)
66
+ text
67
+ end
68
+
69
+ def resolve_file_with_dir(path_suffix)
70
+ settings[:directory].split(/:/).each do |dir|
71
+ dir =
72
+ if '$cwd' == dir
73
+ Dir.pwd
74
+ elsif '$cdir' == dir
75
+ Rubinius::OS_STARTUP_DIR
76
+ elsif '$rbx' == dir
77
+ compiler_file = '/lib/compiler/compiler.rb'
78
+ compiler_rb_path =
79
+ $LOADED_FEATURES.find{|f| f.end_with?(compiler_file)}
80
+ if compiler_rb_path
81
+ compiler_rb_path[0...-(compiler_file.size)]
82
+ else
83
+ nil
84
+ end
85
+ else
86
+ dir
87
+ end
88
+ next unless dir && File.directory?(dir)
89
+ try_file = File.join(dir, path_suffix)
90
+ return try_file if File.readable?(try_file)
91
+ end
92
+ nil
93
+ end
94
+
95
+ # Get line +line_number+ from file named +filename+. Return "\n"
96
+ # there was a problem. Leading blanks are stripped off.
97
+ def line_at(filename, line_number,
98
+ opts = {
99
+ :reload_on_change => @settings[:reload],
100
+ :output => @settings[:highlight]
101
+ })
102
+ # We use linecache first to give precidence to user-remapped
103
+ # file names
104
+ line = LineCache::getline(filename, line_number, opts)
105
+ unless line
106
+ # Try using search directories (set with command "directory")
107
+ if filename[0..0] != File::SEPARATOR
108
+ try_filename = resolve_file_with_dir(filename)
109
+ if try_filename &&
110
+ line = LineCache::getline(try_filename, line_number, opts)
111
+ LineCache::remap_file(filename, try_filename)
112
+ end
113
+ end
114
+ end
115
+ return nil unless line
116
+ return line.lstrip.chomp
117
+ end
118
+
119
+ def loc_and_text(loc, opts=
120
+ {:reload_on_change => @settings[:reload],
121
+ :output => @settings[:highlight]
122
+ })
123
+
124
+ vm_location = @frame.vm_location
125
+ filename = vm_location.method.active_path
126
+ line_no = @frame.line
127
+ static = vm_location.constant_scope
128
+ opts[:compiled_method] = top_scope(@frame.method)
129
+
130
+ if @frame.eval?
131
+ file = LineCache::map_script(static.script)
132
+ text = LineCache::getline(static.script, line_no, opts)
133
+ loc += " remapped #{canonic_file(file)}:#{line_no}"
134
+ else
135
+ text = line_at(filename, line_no, opts)
136
+ map_file, map_line = LineCache::map_file_line(filename, line_no)
137
+ if [filename, line_no] != [map_file, map_line]
138
+ loc += " remapped #{canonic_file(map_file)}:#{map_line}"
139
+ end
140
+ end
141
+ [loc, line_no, text]
142
+ end
143
+
144
+ def format_location(event=@event, frame=@frame, frame_index=@frame_index)
145
+ text = nil
146
+ ev = if event.nil? || 0 != frame_index
147
+ ' '
148
+ else
149
+ (EVENT2ICON[event] || event)
150
+ end
151
+
152
+ @line_no = frame.line
153
+
154
+ loc = source_location_info
155
+ loc, @line_no, text = loc_and_text(loc)
156
+ ip_str = frame.method ? " @#{frame.next_ip}" : ''
157
+
158
+ "#{ev} (#{loc}#{ip_str})"
159
+ end
160
+
161
+ # FIXME: Use above format_location routine
162
+ def print_location
163
+ text = nil
164
+ ev = if @event.nil? || 0 != @frame_index
165
+ ' '
166
+ else
167
+ (EVENT2ICON[@event] || @event)
168
+ end
169
+
170
+ @line_no = @frame.line
171
+
172
+ loc = source_location_info
173
+ loc, @line_no, text = loc_and_text(loc)
174
+ ip_str = frame.method ? " @#{frame.next_ip}" : ''
175
+
176
+ msg "#{ev} (#{loc}#{ip_str})"
177
+
178
+ # if %w(return c-return).member?(@core.event)
179
+ # retval = Trepan::Frame.value_returned(@frame, @core.event)
180
+ # msg 'R=> %s' % retval.inspect
181
+ # end
182
+
183
+ if text && !text.strip.empty?
184
+ old_maxstring = @settings[:maxstring]
185
+ @settings[:maxstring] = -1
186
+ msg text
187
+ @settings[:maxstring] = old_maxstring
188
+ @line_no -= 1
189
+ else
190
+ show_bytecode
191
+ end
192
+ end
193
+
194
+ def source_location_info
195
+ filename = @frame.vm_location.method.active_path
196
+ canonic_filename =
197
+ if @frame.eval?
198
+ 'eval ' + safe_repr(@frame.eval_string.gsub("\n", ';').inspect, 20)
199
+ else
200
+ canonic_file(filename, false)
201
+ end
202
+ loc = "#{canonic_filename}:#{@frame.line}"
203
+ return loc
204
+ end
205
+ end
206
+
207
+ if __FILE__ == $0 && caller.size == 0
208
+ # Demo it.
209
+ require_relative './mock'
210
+ dbgr = MockDebugger::MockDebugger.new
211
+ proc = Trepan::CmdProcessor.new(dbgr)
212
+ proc.settings = {:directory => '$rbx:$cdir:$cwd'}
213
+ proc.frame_initialize
214
+ frame = Trepan::Frame.new(self, 1, Rubinius::VM.backtrace(0)[0])
215
+ proc.instance_variable_set('@frame', frame)
216
+
217
+ puts proc.canonic_file(__FILE__)
218
+ puts proc.canonic_file('lib/compiler/ast.rb')
219
+ proc.settings[:basename] = true
220
+ puts proc.canonic_file(__FILE__)
221
+ puts proc.current_source_text
222
+ xx = eval <<-END
223
+ proc.frame_initialize
224
+ frame = Trepan::Frame.new(self, 1, Rubinius::VM.backtrace(0)[0])
225
+ proc.instance_variable_set('@frame', frame)
226
+ puts proc.current_source_text
227
+ END
228
+ end