debug 0.2.0 → 1.0.0.alpha0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ef5033a78a878b42dd6850ee75552d58a0a0e02bfb890b3bf8970d9b5076387
4
- data.tar.gz: a20c0455d990c8d74975ee9d67c327cfd9165f50a6ae32e6a69d79d6334bed56
3
+ metadata.gz: 58f91a1d4079133e3e7590329d65b7b811490f7158ef96d7b3f826968bc3ad1f
4
+ data.tar.gz: 4da17de6911dc4506cb869298d84df46de08121aca704bb9e2643f774015fbb3
5
5
  SHA512:
6
- metadata.gz: 8421e8a499c15e797ccced0f4f6ee2e315c9a18332db39beac30978fdcc87ac541c765fbf1c6e31b577020949421a928139dc81d3bf0ed0fcc97f7d7e2158487
7
- data.tar.gz: bcab6869de9e3522bfa139a610ad5964121da2fd69678966fc0ab2c10d0b544d9692bbb2614e794b2df44ab7469d556fb86983be8dc6971c402c33ba816a6dc3
6
+ metadata.gz: baa1a1708b02b63f47d7d751ce9e5830edcdc690c8ca84c956f0e4ce839db5f3f63cf22e856ad4cec43190bb7401b8dcfd13a3d55de72d0a438520a3fab394bc
7
+ data.tar.gz: 3816a302b56757b55501950ff2814e21d978a5cdf58a4431d663bd1dfbdaae1c7652e0a9565e4401201b29119cdfaa35f47986eee1b17b0b60c1759ec21f3e6a
data/.gitignore CHANGED
@@ -6,4 +6,3 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
- /Gemfile.lock
data/LICENSE.txt CHANGED
@@ -1,22 +1,21 @@
1
- Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
1
+ The MIT License (MIT)
2
2
 
3
- Redistribution and use in source and binary forms, with or without
4
- modification, are permitted provided that the following conditions
5
- are met:
6
- 1. Redistributions of source code must retain the above copyright
7
- notice, this list of conditions and the following disclaimer.
8
- 2. Redistributions in binary form must reproduce the above copyright
9
- notice, this list of conditions and the following disclaimer in the
10
- documentation and/or other materials provided with the distribution.
3
+ Copyright (c) 2021 Koichi Sasada
11
4
 
12
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
- SUCH DAMAGE.
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,52 +1,166 @@
1
- # Debug
1
+ # debug.rb
2
2
 
3
- This library provides debugging functionality to Ruby.
3
+ ## How to install
4
4
 
5
- ## Installation
5
+ This is temporary installation guide until gemify.
6
6
 
7
- Add this line to your application's Gemfile:
7
+ ```
8
+ $ git clone https://github.com/ko1/debug.git
9
+ $ gem install debug_inspector
10
+ $ gem install iseq_collector
11
+ $ export RUBYOPT=-I`pwd`/debug/lib
12
+ # or add "-I`pwd`/debug/lib" for the following command
13
+ ```
14
+
15
+ # How to use
16
+
17
+ ## Invoke with debugger
18
+
19
+ ### REPL debug
8
20
 
9
- ```ruby
10
- gem 'debug'
21
+ ```
22
+ $ ruby -r debug target.rb
11
23
  ```
12
24
 
13
- And then execute:
25
+ and you can see the debugger prompt. The program was suspended at the beggining of target.rb. To continue the program, type `c` (or `continue`). See other debug commands below.
14
26
 
15
- $ bundle install
27
+ You can re-enable debug command mode by `Ctrl-C`.
16
28
 
17
- Or install it yourself as:
29
+ ### Remote debug (1) UNIX domain socket
18
30
 
19
- $ gem install debug
31
+ ```
32
+ $ ruby -r debug/unixserver target.rb
33
+ ```
20
34
 
21
- ## Usage
35
+ It runs target.rb and accept debugger connection within UNIX domain socket.
22
36
 
23
- To add a debugger to your code, start by requiring +debug+ in your
24
- program:
37
+ You can attach the program with the folliowing command:
25
38
 
26
- ```ruby
27
- def say(word)
28
- require 'debug'
29
- puts word
30
- end
39
+ ```
40
+ $ ruby -r debug/client -e connect
41
+ Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-20642)
42
+ ...
31
43
  ```
32
44
 
33
- This will cause Ruby to interrupt execution and show a prompt when the +say+
34
- method is run.
45
+ The debugee process will be suspended and wait for the debug command.
35
46
 
36
- Once you're inside the prompt, you can start debugging your program.
47
+ If you are running multiple debuggee processes, this command shows the selection like that:
37
48
 
38
49
  ```
39
- (rdb:1) p word
40
- "hello"
50
+ $ ruby -r debug/client -e connect
51
+ Please select a debug session:
52
+ ruby-debug-ko1-19638
53
+ ruby-debug-ko1-19603
41
54
  ```
42
55
 
43
- ## Development
56
+ and you need to specify one:
44
57
 
45
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
58
+ ```
59
+ $ ruby -r debug/client -e connect ruby-debug-ko1-19638
60
+ ```
61
+
62
+ The socket file is located at
63
+ * `RUBY_DEBUG_SOCK_DIR` environment variable if available.
64
+ * `XDG_RUNTIME_DIR` environment variable if available.
65
+ * `$HOME/ruby-debug-sock` if `$HOME` is available.
46
66
 
47
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
67
+ ### Remote debug (2) TCP/IP
48
68
 
49
- ## Contributing
69
+ ```
70
+ $ RUBY_DEBUG_PORT=12345 RUBY_DEBUG_HOST=localhost ruby -r debug/tcpserver target.rb
71
+ Debugger can attach via TCP/IP (localhost:12345)
72
+ ...
73
+ ```
74
+
75
+ This command invoke target.rb with TCP/IP attach server with given port and host. If host is not given, `localhost` will be used.
76
+
77
+ ```
78
+ $ ruby -r debug/client -e connect localhost 12345
79
+ ```
50
80
 
51
- Bug reports and pull requests are welcome on GitHub at https://github.com/hsbt/debug.
81
+ tries to connect with given host (`localhost`) and port (`12345`). You can eliminate host part and `localhost` will be used.
82
+
83
+
84
+ ## Debug command
85
+
86
+ * `Enter` repeats the last command (useful when repeating `step`s).
87
+ * `Ctrl-D` is equal to `quit` command.
88
+
89
+ ### Control flow
90
+
91
+ * `s[tep]`
92
+ * Step in. Resume the program until next breakable point.
93
+ * `n[ext]`
94
+ * Step over. Resume the program until next line.
95
+ * `fin[ish]`
96
+ * Finish this frame. Resume the program until the current frame is finished.
97
+ * `c[ontinue]`
98
+ * Resume the program.
99
+ * `q[uit]` or `Ctrl-D`
100
+ * Finish debugger (with a process, if not remote debugging).
101
+ * `kill`
102
+ * Stop the debuggee program.
103
+
104
+ ### Breakpoint
105
+
106
+ * `b[reak]`
107
+ * Show all breakpoints.
108
+ * `b[reak] <line>`
109
+ * Set breakpoint on `<line>` at the current frame's file.
110
+ * `b[reak] <file>:<line>`
111
+ * Set breakpoint on `<file>:<line>`.
112
+ * `catch <Error>`
113
+ * Set breakpoint on raising `<Error>`.
114
+ * `del[ete]`
115
+ * delete all breakpoints.
116
+ * `del[ete] <bpnum>`
117
+ * delete specified breakpoint.
118
+
119
+ ### Frame control
120
+
121
+ * `bt` or `backtrace`
122
+ * Show backtrace information.
123
+ * `f[rame]`
124
+ * Show current frame.
125
+ * `f[rame] <framenum>`
126
+ * Specify frame. Evaluation are run on this frame environement.
127
+ * `up`
128
+ * Specify upper frame.
129
+ * `down`
130
+ * Specify down frame.
131
+
132
+ ### Evaluate
133
+
134
+ * `p <expr>`
135
+ * Evaluate like `p <expr>` on the current frame.
136
+ * `pp <expr>`
137
+ * Evaluate like `pp <expr>` on the current frame.
138
+ * `e[val] <expr>`
139
+ * Evaluate `<expr>` on the current frame.
140
+
141
+ ### Information
142
+
143
+ * `list`
144
+ * Show current frame's source code.
145
+ * `info l[ocal[s]]`
146
+ * Show current frame's local variables. It includes `self` as `%self` and a return value as `%return`.
147
+ * `info i[nstance]` or `info ivars`
148
+ * Show current frame's insntance variables.
149
+ * `display`
150
+ * Show display setting.
151
+ * `display <expr>`
152
+ * Add `<expr>` at suspended timing.
153
+ * `undisplay`
154
+ * Remove all display settings.
155
+ * `undisplay <displaynum>`
156
+ * Remove a specified display setting.
157
+ * `trace [on|off]`
158
+ * enable or disable line tracer.
159
+
160
+ ### Thread control
161
+
162
+ * `th[read] [l[ist]]`
163
+ * Show all threads.
164
+ * `th[read] <thnum>`
165
+ * Switch thread specified by `<thnum>`
52
166
 
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/debug.gemspec CHANGED
@@ -1,22 +1,32 @@
1
+ require_relative 'lib/debug/version'
2
+
1
3
  Gem::Specification.new do |spec|
2
4
  spec.name = "debug"
3
- spec.version = "0.2.0"
4
- spec.authors = ["Yukihiro Matsumoto"]
5
- spec.email = ["matz@ruby-lang.org"]
5
+ spec.version = DEBUGGER__::VERSION
6
+ spec.authors = ["Koichi Sasada"]
7
+ spec.email = ["ko1@atdot.net"]
8
+
9
+ spec.summary = %q{debug.rb}
10
+ spec.description = %q{debug.rb}
11
+ spec.homepage = "https://github.com/ko1/debug"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
6
14
 
7
- spec.summary = %q{Debugging functionality for Ruby}
8
- spec.description = %q{Debugging functionality for Ruby}
9
- spec.homepage = "https://github.com/ruby/debug"
10
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
11
- spec.licenses = ["Ruby", "BSD-2-Clause"]
15
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
12
16
 
13
17
  spec.metadata["homepage_uri"] = spec.homepage
14
- spec.metadata["source_code_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/ko1/debug"
19
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
15
20
 
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
16
23
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
24
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
25
  end
19
26
  spec.bindir = "exe"
20
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
28
  spec.require_paths = ["lib"]
29
+
30
+ spec.add_runtime_dependency 'debug_inspector'
31
+ spec.add_runtime_dependency 'iseq_collector'
22
32
  end
data/exe/rdbg ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "debug"
data/lib/debug.rb CHANGED
@@ -1,1111 +1,15 @@
1
- # frozen_string_literal: true
2
- # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
3
- # Copyright (C) 2000 Information-technology Promotion Agency, Japan
4
- # Copyright (C) 2000-2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
1
+ require_relative 'debug/repl'
5
2
 
6
- require 'continuation'
7
-
8
- if $SAFE > 0
9
- STDERR.print "-r debug.rb is not available in safe mode\n"
10
- exit 1
11
- end
12
-
13
- require 'tracer'
14
- require 'pp'
15
-
16
- class Tracer # :nodoc:
17
- def Tracer.trace_func(*vars)
18
- Single.trace_func(*vars)
19
- end
3
+ # default break points
4
+ DEBUGGER__.add_catch_breakpoint 'RuntimeError'
5
+ class Binding
6
+ DEBUGGER__.add_line_breakpoint __FILE__, __LINE__ + 1
7
+ def bp; nil; end
20
8
  end
21
9
 
22
- SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ # :nodoc:
23
-
24
- ##
25
- # This library provides debugging functionality to Ruby.
26
- #
27
- # To add a debugger to your code, start by requiring +debug+ in your
28
- # program:
29
- #
30
- # def say(word)
31
- # require 'debug'
32
- # puts word
33
- # end
34
- #
35
- # This will cause Ruby to interrupt execution and show a prompt when the +say+
36
- # method is run.
37
- #
38
- # Once you're inside the prompt, you can start debugging your program.
39
- #
40
- # (rdb:1) p word
41
- # "hello"
42
- #
43
- # == Getting help
44
- #
45
- # You can get help at any time by pressing +h+.
46
- #
47
- # (rdb:1) h
48
- # Debugger help v.-0.002b
49
- # Commands
50
- # b[reak] [file:|class:]<line|method>
51
- # b[reak] [class.]<line|method>
52
- # set breakpoint to some position
53
- # wat[ch] <expression> set watchpoint to some expression
54
- # cat[ch] (<exception>|off) set catchpoint to an exception
55
- # b[reak] list breakpoints
56
- # cat[ch] show catchpoint
57
- # del[ete][ nnn] delete some or all breakpoints
58
- # disp[lay] <expression> add expression into display expression list
59
- # undisp[lay][ nnn] delete one particular or all display expressions
60
- # c[ont] run until program ends or hit breakpoint
61
- # s[tep][ nnn] step (into methods) one line or till line nnn
62
- # n[ext][ nnn] go over one line or till line nnn
63
- # w[here] display frames
64
- # f[rame] alias for where
65
- # l[ist][ (-|nn-mm)] list program, - lists backwards
66
- # nn-mm lists given lines
67
- # up[ nn] move to higher frame
68
- # down[ nn] move to lower frame
69
- # fin[ish] return to outer frame
70
- # tr[ace] (on|off) set trace mode of current thread
71
- # tr[ace] (on|off) all set trace mode of all threads
72
- # q[uit] exit from debugger
73
- # v[ar] g[lobal] show global variables
74
- # v[ar] l[ocal] show local variables
75
- # v[ar] i[nstance] <object> show instance variables of object
76
- # v[ar] c[onst] <object> show constants of object
77
- # m[ethod] i[nstance] <obj> show methods of object
78
- # m[ethod] <class|module> show instance methods of class or module
79
- # th[read] l[ist] list all threads
80
- # th[read] c[ur[rent]] show current thread
81
- # th[read] [sw[itch]] <nnn> switch thread context to nnn
82
- # th[read] stop <nnn> stop thread nnn
83
- # th[read] resume <nnn> resume thread nnn
84
- # p expression evaluate expression and print its value
85
- # h[elp] print this help
86
- # <everything else> evaluate
87
- #
88
- # == Usage
89
- #
90
- # The following is a list of common functionalities that the debugger
91
- # provides.
92
- #
93
- # === Navigating through your code
94
- #
95
- # In general, a debugger is used to find bugs in your program, which
96
- # often means pausing execution and inspecting variables at some point
97
- # in time.
98
- #
99
- # Let's look at an example:
100
- #
101
- # def my_method(foo)
102
- # require 'debug'
103
- # foo = get_foo if foo.nil?
104
- # raise if foo.nil?
105
- # end
106
- #
107
- # When you run this program, the debugger will kick in just before the
108
- # +foo+ assignment.
109
- #
110
- # (rdb:1) p foo
111
- # nil
112
- #
113
- # In this example, it'd be interesting to move to the next line and
114
- # inspect the value of +foo+ again. You can do that by pressing +n+:
115
- #
116
- # (rdb:1) n # goes to next line
117
- # (rdb:1) p foo
118
- # nil
119
- #
120
- # You now know that the original value of +foo+ was nil, and that it
121
- # still was nil after calling +get_foo+.
122
- #
123
- # Other useful commands for navigating through your code are:
124
- #
125
- # +c+::
126
- # Runs the program until it either exists or encounters another breakpoint.
127
- # You usually press +c+ when you are finished debugging your program and
128
- # want to resume its execution.
129
- # +s+::
130
- # Steps into method definition. In the previous example, +s+ would take you
131
- # inside the method definition of +get_foo+.
132
- # +r+::
133
- # Restart the program.
134
- # +q+::
135
- # Quit the program.
136
- #
137
- # === Inspecting variables
138
- #
139
- # You can use the debugger to easily inspect both local and global variables.
140
- # We've seen how to inspect local variables before:
141
- #
142
- # (rdb:1) p my_arg
143
- # 42
144
- #
145
- # You can also pretty print the result of variables or expressions:
146
- #
147
- # (rdb:1) pp %w{a very long long array containing many words}
148
- # ["a",
149
- # "very",
150
- # "long",
151
- # ...
152
- # ]
153
- #
154
- # You can list all local variables with +v l+:
155
- #
156
- # (rdb:1) v l
157
- # foo => "hello"
158
- #
159
- # Similarly, you can show all global variables with +v g+:
160
- #
161
- # (rdb:1) v g
162
- # all global variables
163
- #
164
- # Finally, you can omit +p+ if you simply want to evaluate a variable or
165
- # expression
166
- #
167
- # (rdb:1) 5**2
168
- # 25
169
- #
170
- # === Going beyond basics
171
- #
172
- # Ruby Debug provides more advanced functionalities like switching
173
- # between threads, setting breakpoints and watch expressions, and more.
174
- # The full list of commands is available at any time by pressing +h+.
175
- #
176
- # == Staying out of trouble
177
- #
178
- # Make sure you remove every instance of +require 'debug'+ before
179
- # shipping your code. Failing to do so may result in your program
180
- # hanging unpredictably.
181
- #
182
- # Debug is not available in safe mode.
183
-
184
- class DEBUGGER__
185
- MUTEX = Thread::Mutex.new # :nodoc:
186
-
187
- class Context # :nodoc:
188
- DEBUG_LAST_CMD = []
189
-
190
- begin
191
- require 'readline'
192
- def readline(prompt, hist)
193
- Readline::readline(prompt, hist)
194
- end
195
- rescue LoadError
196
- def readline(prompt, hist)
197
- STDOUT.print prompt
198
- STDOUT.flush
199
- line = STDIN.gets
200
- exit unless line
201
- line.chomp!
202
- line
203
- end
204
- USE_READLINE = false
205
- end
206
-
207
- def initialize
208
- if Thread.current == Thread.main
209
- @stop_next = 1
210
- else
211
- @stop_next = 0
212
- end
213
- @last_file = nil
214
- @file = nil
215
- @line = nil
216
- @no_step = nil
217
- @frames = []
218
- @finish_pos = 0
219
- @trace = false
220
- @catch = "StandardError"
221
- @suspend_next = false
222
- end
223
-
224
- def stop_next(n=1)
225
- @stop_next = n
226
- end
227
-
228
- def set_suspend
229
- @suspend_next = true
230
- end
231
-
232
- def clear_suspend
233
- @suspend_next = false
234
- end
235
-
236
- def suspend_all
237
- DEBUGGER__.suspend
238
- end
239
-
240
- def resume_all
241
- DEBUGGER__.resume
242
- end
243
-
244
- def check_suspend
245
- while MUTEX.synchronize {
246
- if @suspend_next
247
- DEBUGGER__.waiting.push Thread.current
248
- @suspend_next = false
249
- true
250
- end
251
- }
252
- end
253
- end
254
-
255
- def trace?
256
- @trace
257
- end
258
-
259
- def set_trace(arg)
260
- @trace = arg
261
- end
262
-
263
- def stdout
264
- DEBUGGER__.stdout
265
- end
266
-
267
- def break_points
268
- DEBUGGER__.break_points
269
- end
270
-
271
- def display
272
- DEBUGGER__.display
273
- end
274
-
275
- def context(th)
276
- DEBUGGER__.context(th)
277
- end
278
-
279
- def set_trace_all(arg)
280
- DEBUGGER__.set_trace(arg)
281
- end
282
-
283
- def set_last_thread(th)
284
- DEBUGGER__.set_last_thread(th)
285
- end
286
-
287
- def debug_eval(str, binding)
288
- begin
289
- eval(str, binding)
290
- rescue StandardError, ScriptError => e
291
- at = eval("caller(1)", binding)
292
- stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
293
- for i in at
294
- stdout.printf "\tfrom %s\n", i
295
- end
296
- throw :debug_error
297
- end
298
- end
299
-
300
- def debug_silent_eval(str, binding)
301
- begin
302
- eval(str, binding)
303
- rescue StandardError, ScriptError
304
- nil
305
- end
306
- end
307
-
308
- def var_list(ary, binding)
309
- ary.sort!
310
- for v in ary
311
- stdout.printf " %s => %s\n", v, eval(v.to_s, binding).inspect
312
- end
313
- end
314
-
315
- def debug_variable_info(input, binding)
316
- case input
317
- when /^\s*g(?:lobal)?\s*$/
318
- var_list(global_variables, binding)
319
-
320
- when /^\s*l(?:ocal)?\s*$/
321
- var_list(eval("local_variables", binding), binding)
322
-
323
- when /^\s*i(?:nstance)?\s+/
324
- obj = debug_eval($', binding)
325
- var_list(obj.instance_variables, obj.instance_eval{binding()})
326
-
327
- when /^\s*c(?:onst(?:ant)?)?\s+/
328
- obj = debug_eval($', binding)
329
- unless obj.kind_of? Module
330
- stdout.print "Should be Class/Module: ", $', "\n"
331
- else
332
- var_list(obj.constants, obj.module_eval{binding()})
333
- end
334
- end
335
- end
336
-
337
- def debug_method_info(input, binding)
338
- case input
339
- when /^i(:?nstance)?\s+/
340
- obj = debug_eval($', binding)
341
-
342
- len = 0
343
- for v in obj.methods.sort
344
- len += v.size + 1
345
- if len > 70
346
- len = v.size + 1
347
- stdout.print "\n"
348
- end
349
- stdout.print v, " "
350
- end
351
- stdout.print "\n"
352
-
353
- else
354
- obj = debug_eval(input, binding)
355
- unless obj.kind_of? Module
356
- stdout.print "Should be Class/Module: ", input, "\n"
357
- else
358
- len = 0
359
- for v in obj.instance_methods(false).sort
360
- len += v.size + 1
361
- if len > 70
362
- len = v.size + 1
363
- stdout.print "\n"
364
- end
365
- stdout.print v, " "
366
- end
367
- stdout.print "\n"
368
- end
369
- end
370
- end
371
-
372
- def thnum
373
- num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
374
- unless num
375
- DEBUGGER__.make_thread_list
376
- num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
377
- end
378
- num
379
- end
380
-
381
- def debug_command(file, line, id, binding)
382
- MUTEX.lock
383
- unless defined?($debugger_restart) and $debugger_restart
384
- callcc{|c| $debugger_restart = c}
385
- end
386
- set_last_thread(Thread.current)
387
- frame_pos = 0
388
- binding_file = file
389
- binding_line = line
390
- previous_line = nil
391
- if ENV['EMACS']
392
- stdout.printf "\032\032%s:%d:\n", binding_file, binding_line
393
- else
394
- stdout.printf "%s:%d:%s", binding_file, binding_line,
395
- line_at(binding_file, binding_line)
396
- end
397
- @frames[0] = [binding, file, line, id]
398
- display_expressions(binding)
399
- prompt = true
400
- while prompt and input = readline("(rdb:%d) "%thnum(), true)
401
- catch(:debug_error) do
402
- if input == ""
403
- next unless DEBUG_LAST_CMD[0]
404
- input = DEBUG_LAST_CMD[0]
405
- stdout.print input, "\n"
406
- else
407
- DEBUG_LAST_CMD[0] = input
408
- end
409
-
410
- case input
411
- when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
412
- if defined?( $2 )
413
- if $1 == 'on'
414
- set_trace_all true
415
- else
416
- set_trace_all false
417
- end
418
- elsif defined?( $1 )
419
- if $1 == 'on'
420
- set_trace true
421
- else
422
- set_trace false
423
- end
424
- end
425
- if trace?
426
- stdout.print "Trace on.\n"
427
- else
428
- stdout.print "Trace off.\n"
429
- end
430
-
431
- when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/
432
- pos = $2
433
- if $1
434
- klass = debug_silent_eval($1, binding)
435
- file = $1
436
- end
437
- if pos =~ /^\d+$/
438
- pname = pos
439
- pos = pos.to_i
440
- else
441
- pname = pos = pos.intern.id2name
442
- end
443
- break_points.push [true, 0, klass || file, pos]
444
- stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname
445
-
446
- when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/
447
- pos = $2.intern.id2name
448
- klass = debug_eval($1, binding)
449
- break_points.push [true, 0, klass, pos]
450
- stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos
451
-
452
- when /^\s*wat(?:ch)?\s+(.+)$/
453
- exp = $1
454
- break_points.push [true, 1, exp]
455
- stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp
456
-
457
- when /^\s*b(?:reak)?$/
458
- if break_points.find{|b| b[1] == 0}
459
- n = 1
460
- stdout.print "Breakpoints:\n"
461
- break_points.each do |b|
462
- if b[0] and b[1] == 0
463
- stdout.printf " %d %s:%s\n", n, b[2], b[3]
464
- end
465
- n += 1
466
- end
467
- end
468
- if break_points.find{|b| b[1] == 1}
469
- n = 1
470
- stdout.print "\n"
471
- stdout.print "Watchpoints:\n"
472
- for b in break_points
473
- if b[0] and b[1] == 1
474
- stdout.printf " %d %s\n", n, b[2]
475
- end
476
- n += 1
477
- end
478
- end
479
- if break_points.size == 0
480
- stdout.print "No breakpoints\n"
481
- else
482
- stdout.print "\n"
483
- end
484
-
485
- when /^\s*del(?:ete)?(?:\s+(\d+))?$/
486
- pos = $1
487
- unless pos
488
- input = readline("Clear all breakpoints? (y/n) ", false)
489
- if input == "y"
490
- for b in break_points
491
- b[0] = false
492
- end
493
- end
494
- else
495
- pos = pos.to_i
496
- if break_points[pos-1]
497
- break_points[pos-1][0] = false
498
- else
499
- stdout.printf "Breakpoint %d is not defined\n", pos
500
- end
501
- end
502
-
503
- when /^\s*disp(?:lay)?\s+(.+)$/
504
- exp = $1
505
- display.push [true, exp]
506
- stdout.printf "%d: ", display.size
507
- display_expression(exp, binding)
508
-
509
- when /^\s*disp(?:lay)?$/
510
- display_expressions(binding)
511
-
512
- when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
513
- pos = $1
514
- unless pos
515
- input = readline("Clear all expressions? (y/n) ", false)
516
- if input == "y"
517
- for d in display
518
- d[0] = false
519
- end
520
- end
521
- else
522
- pos = pos.to_i
523
- if display[pos-1]
524
- display[pos-1][0] = false
525
- else
526
- stdout.printf "Display expression %d is not defined\n", pos
527
- end
528
- end
529
-
530
- when /^\s*c(?:ont)?$/
531
- prompt = false
532
-
533
- when /^\s*s(?:tep)?(?:\s+(\d+))?$/
534
- if $1
535
- lev = $1.to_i
536
- else
537
- lev = 1
538
- end
539
- @stop_next = lev
540
- prompt = false
541
-
542
- when /^\s*n(?:ext)?(?:\s+(\d+))?$/
543
- if $1
544
- lev = $1.to_i
545
- else
546
- lev = 1
547
- end
548
- @stop_next = lev
549
- @no_step = @frames.size - frame_pos
550
- prompt = false
551
-
552
- when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
553
- display_frames(frame_pos)
554
-
555
- when /^\s*l(?:ist)?(?:\s+(.+))?$/
556
- if not $1
557
- b = previous_line ? previous_line + 10 : binding_line - 5
558
- e = b + 9
559
- elsif $1 == '-'
560
- b = previous_line ? previous_line - 10 : binding_line - 5
561
- e = b + 9
562
- else
563
- b, e = $1.split(/[-,]/)
564
- if e
565
- b = b.to_i
566
- e = e.to_i
567
- else
568
- b = b.to_i - 5
569
- e = b + 9
570
- end
571
- end
572
- previous_line = b
573
- display_list(b, e, binding_file, binding_line)
574
-
575
- when /^\s*up(?:\s+(\d+))?$/
576
- previous_line = nil
577
- if $1
578
- lev = $1.to_i
579
- else
580
- lev = 1
581
- end
582
- frame_pos += lev
583
- if frame_pos >= @frames.size
584
- frame_pos = @frames.size - 1
585
- stdout.print "At toplevel\n"
586
- end
587
- binding, binding_file, binding_line = @frames[frame_pos]
588
- stdout.print format_frame(frame_pos)
589
-
590
- when /^\s*down(?:\s+(\d+))?$/
591
- previous_line = nil
592
- if $1
593
- lev = $1.to_i
594
- else
595
- lev = 1
596
- end
597
- frame_pos -= lev
598
- if frame_pos < 0
599
- frame_pos = 0
600
- stdout.print "At stack bottom\n"
601
- end
602
- binding, binding_file, binding_line = @frames[frame_pos]
603
- stdout.print format_frame(frame_pos)
604
-
605
- when /^\s*fin(?:ish)?$/
606
- if frame_pos == @frames.size
607
- stdout.print "\"finish\" not meaningful in the outermost frame.\n"
608
- else
609
- @finish_pos = @frames.size - frame_pos
610
- frame_pos = 0
611
- prompt = false
612
- end
613
-
614
- when /^\s*cat(?:ch)?(?:\s+(.+))?$/
615
- if $1
616
- excn = $1
617
- if excn == 'off'
618
- @catch = nil
619
- stdout.print "Clear catchpoint.\n"
620
- else
621
- @catch = excn
622
- stdout.printf "Set catchpoint %s.\n", @catch
623
- end
624
- else
625
- if @catch
626
- stdout.printf "Catchpoint %s.\n", @catch
627
- else
628
- stdout.print "No catchpoint.\n"
629
- end
630
- end
631
-
632
- when /^\s*q(?:uit)?$/
633
- input = readline("Really quit? (y/n) ", false)
634
- if input == "y"
635
- exit! # exit -> exit!: No graceful way to stop threads...
636
- end
637
-
638
- when /^\s*v(?:ar)?\s+/
639
- debug_variable_info($', binding)
640
-
641
- when /^\s*m(?:ethod)?\s+/
642
- debug_method_info($', binding)
643
-
644
- when /^\s*th(?:read)?\s+/
645
- if DEBUGGER__.debug_thread_info($', binding) == :cont
646
- prompt = false
647
- end
648
-
649
- when /^\s*pp\s+/
650
- PP.pp(debug_eval($', binding), stdout)
651
-
652
- when /^\s*p\s+/
653
- stdout.printf "%s\n", debug_eval($', binding).inspect
654
-
655
- when /^\s*r(?:estart)?$/
656
- $debugger_restart.call
657
-
658
- when /^\s*h(?:elp)?$/
659
- debug_print_help()
660
-
661
- else
662
- v = debug_eval(input, binding)
663
- stdout.printf "%s\n", v.inspect
664
- end
665
- end
666
- end
667
- MUTEX.unlock
668
- resume_all
669
- end
670
-
671
- def debug_print_help
672
- stdout.print <<EOHELP
673
- Debugger help v.-0.002b
674
- Commands
675
- b[reak] [file:|class:]<line|method>
676
- b[reak] [class.]<line|method>
677
- set breakpoint to some position
678
- wat[ch] <expression> set watchpoint to some expression
679
- cat[ch] (<exception>|off) set catchpoint to an exception
680
- b[reak] list breakpoints
681
- cat[ch] show catchpoint
682
- del[ete][ nnn] delete some or all breakpoints
683
- disp[lay] <expression> add expression into display expression list
684
- undisp[lay][ nnn] delete one particular or all display expressions
685
- c[ont] run until program ends or hit breakpoint
686
- s[tep][ nnn] step (into methods) one line or till line nnn
687
- n[ext][ nnn] go over one line or till line nnn
688
- w[here] display frames
689
- f[rame] alias for where
690
- l[ist][ (-|nn-mm)] list program, - lists backwards
691
- nn-mm lists given lines
692
- up[ nn] move to higher frame
693
- down[ nn] move to lower frame
694
- fin[ish] return to outer frame
695
- tr[ace] (on|off) set trace mode of current thread
696
- tr[ace] (on|off) all set trace mode of all threads
697
- q[uit] exit from debugger
698
- v[ar] g[lobal] show global variables
699
- v[ar] l[ocal] show local variables
700
- v[ar] i[nstance] <object> show instance variables of object
701
- v[ar] c[onst] <object> show constants of object
702
- m[ethod] i[nstance] <obj> show methods of object
703
- m[ethod] <class|module> show instance methods of class or module
704
- th[read] l[ist] list all threads
705
- th[read] c[ur[rent]] show current thread
706
- th[read] [sw[itch]] <nnn> switch thread context to nnn
707
- th[read] stop <nnn> stop thread nnn
708
- th[read] resume <nnn> resume thread nnn
709
- pp expression evaluate expression and pretty_print its value
710
- p expression evaluate expression and print its value
711
- r[estart] restart program
712
- h[elp] print this help
713
- <everything else> evaluate
714
- EOHELP
715
- end
716
-
717
- def display_expressions(binding)
718
- n = 1
719
- for d in display
720
- if d[0]
721
- stdout.printf "%d: ", n
722
- display_expression(d[1], binding)
723
- end
724
- n += 1
725
- end
726
- end
727
-
728
- def display_expression(exp, binding)
729
- stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
730
- end
731
-
732
- def frame_set_pos(file, line)
733
- if @frames[0]
734
- @frames[0][1] = file
735
- @frames[0][2] = line
736
- end
737
- end
738
-
739
- def display_frames(pos)
740
- 0.upto(@frames.size - 1) do |n|
741
- if n == pos
742
- stdout.print "--> "
743
- else
744
- stdout.print " "
745
- end
746
- stdout.print format_frame(n)
747
- end
748
- end
749
-
750
- def format_frame(pos)
751
- _, file, line, id = @frames[pos]
752
- sprintf "#%d %s:%s%s\n", pos + 1, file, line,
753
- (id ? ":in `#{id.id2name}'" : "")
754
- end
755
-
756
- def script_lines(file, line)
757
- unless (lines = SCRIPT_LINES__[file]) and lines != true
758
- Tracer::Single.get_line(file, line) if File.exist?(file)
759
- lines = SCRIPT_LINES__[file]
760
- lines = nil if lines == true
761
- end
762
- lines
763
- end
764
-
765
- def display_list(b, e, file, line)
766
- if lines = script_lines(file, line)
767
- stdout.printf "[%d, %d] in %s\n", b, e, file
768
- b.upto(e) do |n|
769
- if n > 0 && lines[n-1]
770
- if n == line
771
- stdout.printf "=> %d %s\n", n, lines[n-1].chomp
772
- else
773
- stdout.printf " %d %s\n", n, lines[n-1].chomp
774
- end
775
- end
776
- end
777
- else
778
- stdout.printf "No sourcefile available for %s\n", file
779
- end
780
- end
781
-
782
- def line_at(file, line)
783
- lines = script_lines(file, line)
784
- if lines and line = lines[line-1]
785
- return line
786
- end
787
- return "\n"
788
- end
789
-
790
- def debug_funcname(id)
791
- if id.nil?
792
- "toplevel"
793
- else
794
- id.id2name
795
- end
796
- end
797
-
798
- def check_break_points(file, klass, pos, binding, id)
799
- return false if break_points.empty?
800
- n = 1
801
- for b in break_points
802
- if b[0] # valid
803
- if b[1] == 0 # breakpoint
804
- if (b[2] == file and b[3] == pos) or
805
- (klass and b[2] == klass and b[3] == pos)
806
- stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
807
- return true
808
- end
809
- elsif b[1] == 1 # watchpoint
810
- if debug_silent_eval(b[2], binding)
811
- stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
812
- return true
813
- end
814
- end
815
- end
816
- n += 1
817
- end
818
- return false
819
- end
820
-
821
- def excn_handle(file, line, id, binding)
822
- if $!.class <= SystemExit
823
- set_trace_func nil
824
- exit
825
- end
826
-
827
- if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch })
828
- stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class
829
- fs = @frames.size
830
- tb = caller(0)[-fs..-1]
831
- if tb
832
- for i in tb
833
- stdout.printf "\tfrom %s\n", i
834
- end
835
- end
836
- suspend_all
837
- debug_command(file, line, id, binding)
838
- end
839
- end
840
-
841
- def trace_func(event, file, line, id, binding, klass)
842
- Tracer.trace_func(event, file, line, id, binding, klass) if trace?
843
- context(Thread.current).check_suspend
844
- @file = file
845
- @line = line
846
- case event
847
- when 'line'
848
- frame_set_pos(file, line)
849
- if !@no_step or @frames.size == @no_step
850
- @stop_next -= 1
851
- @stop_next = -1 if @stop_next < 0
852
- elsif @frames.size < @no_step
853
- @stop_next = 0 # break here before leaving...
854
- else
855
- # nothing to do. skipped.
856
- end
857
- if @stop_next == 0 or check_break_points(file, nil, line, binding, id)
858
- @no_step = nil
859
- suspend_all
860
- debug_command(file, line, id, binding)
861
- end
862
-
863
- when 'call'
864
- @frames.unshift [binding, file, line, id]
865
- if check_break_points(file, klass, id.id2name, binding, id)
866
- suspend_all
867
- debug_command(file, line, id, binding)
868
- end
869
-
870
- when 'c-call'
871
- frame_set_pos(file, line)
872
-
873
- when 'class'
874
- @frames.unshift [binding, file, line, id]
875
-
876
- when 'return', 'end'
877
- if @frames.size == @finish_pos
878
- @stop_next = 1
879
- @finish_pos = 0
880
- end
881
- @frames.shift
882
-
883
- when 'raise'
884
- excn_handle(file, line, id, binding)
885
-
886
- end
887
- @last_file = file
888
- end
889
- end
890
-
891
- trap("INT") { DEBUGGER__.interrupt }
892
- @last_thread = Thread::main
893
- @max_thread = 1
894
- @thread_list = {Thread::main => 1}
895
- @break_points = []
896
- @display = []
897
- @waiting = []
898
- @stdout = STDOUT
899
-
900
- class << DEBUGGER__
901
- # Returns the IO used as stdout. Defaults to STDOUT
902
- def stdout
903
- @stdout
904
- end
905
-
906
- # Sets the IO used as stdout. Defaults to STDOUT
907
- def stdout=(s)
908
- @stdout = s
909
- end
910
-
911
- # Returns the display expression list
912
- #
913
- # See DEBUGGER__ for more usage
914
- def display
915
- @display
916
- end
917
-
918
- # Returns the list of break points where execution will be stopped.
919
- #
920
- # See DEBUGGER__ for more usage
921
- def break_points
922
- @break_points
923
- end
924
-
925
- # Returns the list of waiting threads.
926
- #
927
- # When stepping through the traces of a function, thread gets suspended, to
928
- # be resumed later.
929
- def waiting
930
- @waiting
931
- end
932
-
933
- def set_trace( arg )
934
- MUTEX.synchronize do
935
- make_thread_list
936
- for th, in @thread_list
937
- context(th).set_trace arg
938
- end
939
- end
940
- arg
941
- end
942
-
943
- def set_last_thread(th)
944
- @last_thread = th
945
- end
946
-
947
- def suspend
948
- MUTEX.synchronize do
949
- make_thread_list
950
- for th, in @thread_list
951
- next if th == Thread.current
952
- context(th).set_suspend
953
- end
954
- end
955
- # Schedule other threads to suspend as soon as possible.
956
- Thread.pass
957
- end
958
-
959
- def resume
960
- MUTEX.synchronize do
961
- make_thread_list
962
- @thread_list.each do |th,|
963
- next if th == Thread.current
964
- context(th).clear_suspend
965
- end
966
- waiting.each do |th|
967
- th.run
968
- end
969
- waiting.clear
970
- end
971
- # Schedule other threads to restart as soon as possible.
972
- Thread.pass
973
- end
974
-
975
- def context(thread=Thread.current)
976
- c = thread[:__debugger_data__]
977
- unless c
978
- thread[:__debugger_data__] = c = Context.new
979
- end
980
- c
981
- end
982
-
983
- def interrupt
984
- context(@last_thread).stop_next
985
- end
986
-
987
- def get_thread(num)
988
- th = @thread_list.key(num)
989
- unless th
990
- @stdout.print "No thread ##{num}\n"
991
- throw :debug_error
992
- end
993
- th
994
- end
995
-
996
- def thread_list(num)
997
- th = get_thread(num)
998
- if th == Thread.current
999
- @stdout.print "+"
1000
- else
1001
- @stdout.print " "
1002
- end
1003
- @stdout.printf "%d ", num
1004
- @stdout.print th.inspect, "\t"
1005
- file = context(th).instance_eval{@file}
1006
- if file
1007
- @stdout.print file,":",context(th).instance_eval{@line}
1008
- end
1009
- @stdout.print "\n"
1010
- end
1011
-
1012
- # Prints all threads in @thread_list to @stdout. Returns a sorted array of
1013
- # values from the @thread_list hash.
1014
- #
1015
- # While in the debugger you can list all of
1016
- # the threads with: <b>DEBUGGER__.thread_list_all</b>
1017
- #
1018
- # (rdb:1) DEBUGGER__.thread_list_all
1019
- # +1 #<Thread:0x007fb2320c03f0 run> debug_me.rb.rb:3
1020
- # 2 #<Thread:0x007fb23218a538@debug_me.rb.rb:3 sleep>
1021
- # 3 #<Thread:0x007fb23218b0f0@debug_me.rb.rb:3 sleep>
1022
- # [1, 2, 3]
1023
- #
1024
- # Your current thread is indicated by a <b>+</b>
1025
- #
1026
- # Additionally you can list all threads with <b>th l</b>
1027
- #
1028
- # (rdb:1) th l
1029
- # +1 #<Thread:0x007f99328c0410 run> debug_me.rb:3
1030
- # 2 #<Thread:0x007f9932938230@debug_me.rb:3 sleep> debug_me.rb:3
1031
- # 3 #<Thread:0x007f9932938e10@debug_me.rb:3 sleep> debug_me.rb:3
1032
- #
1033
- # See DEBUGGER__ for more usage.
1034
-
1035
- def thread_list_all
1036
- for th in @thread_list.values.sort
1037
- thread_list(th)
1038
- end
1039
- end
1040
-
1041
- def make_thread_list
1042
- hash = {}
1043
- for th in Thread::list
1044
- if @thread_list.key? th
1045
- hash[th] = @thread_list[th]
1046
- else
1047
- @max_thread += 1
1048
- hash[th] = @max_thread
1049
- end
1050
- end
1051
- @thread_list = hash
1052
- end
1053
-
1054
- def debug_thread_info(input, binding)
1055
- case input
1056
- when /^l(?:ist)?/
1057
- make_thread_list
1058
- thread_list_all
1059
-
1060
- when /^c(?:ur(?:rent)?)?$/
1061
- make_thread_list
1062
- thread_list(@thread_list[Thread.current])
1063
-
1064
- when /^(?:sw(?:itch)?\s+)?(\d+)/
1065
- make_thread_list
1066
- th = get_thread($1.to_i)
1067
- if th == Thread.current
1068
- @stdout.print "It's the current thread.\n"
1069
- else
1070
- thread_list(@thread_list[th])
1071
- context(th).stop_next
1072
- th.run
1073
- return :cont
1074
- end
1075
-
1076
- when /^stop\s+(\d+)/
1077
- make_thread_list
1078
- th = get_thread($1.to_i)
1079
- if th == Thread.current
1080
- @stdout.print "It's the current thread.\n"
1081
- elsif th.stop?
1082
- @stdout.print "Already stopped.\n"
1083
- else
1084
- thread_list(@thread_list[th])
1085
- context(th).suspend
1086
- end
1087
-
1088
- when /^resume\s+(\d+)/
1089
- make_thread_list
1090
- th = get_thread($1.to_i)
1091
- if th == Thread.current
1092
- @stdout.print "It's the current thread.\n"
1093
- elsif !th.stop?
1094
- @stdout.print "Already running."
1095
- else
1096
- thread_list(@thread_list[th])
1097
- th.run
1098
- end
1099
- end
1100
- end
1101
- end
1102
-
1103
- stdout.printf "Debug.rb\n"
1104
- stdout.printf "Emacs support available.\n\n"
1105
- RubyVM::InstructionSequence.compile_option = {
1106
- trace_instruction: true
1107
- }
1108
- set_trace_func proc { |event, file, line, id, binding, klass, *rest|
1109
- DEBUGGER__.context.trace_func event, file, line, id, binding, klass
1110
- }
10
+ if $0 == __FILE__
11
+ # DEBUGGER__.add_line_breakpoint __dir__ + '/target.rb', 1
12
+ # load __dir__ + '/target.rb'
13
+ else
14
+ DEBUGGER__.add_line_breakpoint $0, 1
1111
15
  end