opt
/
alt
/
ruby26
/
lib64
/
ruby
/
2.6.0
/
Go to Home Directory
+
Upload
Create File
root@0UT1S:~$
Execute
By Order of Mr.0UT1S
[DIR] ..
N/A
[DIR] bundler
N/A
[DIR] cgi
N/A
[DIR] csv
N/A
[DIR] digest
N/A
[DIR] drb
N/A
[DIR] e2mmap
N/A
[DIR] fiddle
N/A
[DIR] fileutils
N/A
[DIR] forwardable
N/A
[DIR] io
N/A
[DIR] irb
N/A
[DIR] json
N/A
[DIR] matrix
N/A
[DIR] net
N/A
[DIR] openssl
N/A
[DIR] optparse
N/A
[DIR] psych
N/A
[DIR] racc
N/A
[DIR] rdoc
N/A
[DIR] rexml
N/A
[DIR] rinda
N/A
[DIR] ripper
N/A
[DIR] rss
N/A
[DIR] rubygems
N/A
[DIR] shell
N/A
[DIR] syslog
N/A
[DIR] thwait
N/A
[DIR] tracer
N/A
[DIR] unicode_normalize
N/A
[DIR] uri
N/A
[DIR] webrick
N/A
[DIR] x86_64-linux
N/A
[DIR] yaml
N/A
English.rb
6.31 KB
Rename
Delete
abbrev.rb
3.49 KB
Rename
Delete
base64.rb
3.30 KB
Rename
Delete
benchmark.rb
18.07 KB
Rename
Delete
bigdecimal.rb
179 bytes
Rename
Delete
bundler.rb
17.82 KB
Rename
Delete
cgi.rb
9.80 KB
Rename
Delete
cmath.rb
9.49 KB
Rename
Delete
coverage.rb
368 bytes
Rename
Delete
csv.rb
52.00 KB
Rename
Delete
date.rb
1.01 KB
Rename
Delete
debug.rb
29.97 KB
Rename
Delete
delegate.rb
10.44 KB
Rename
Delete
digest.rb
2.83 KB
Rename
Delete
drb.rb
50 bytes
Rename
Delete
e2mmap.rb
3.94 KB
Rename
Delete
erb.rb
28.73 KB
Rename
Delete
expect.rb
2.17 KB
Rename
Delete
fiddle.rb
1.68 KB
Rename
Delete
fileutils.rb
47.16 KB
Rename
Delete
find.rb
2.47 KB
Rename
Delete
forwardable.rb
8.49 KB
Rename
Delete
getoptlong.rb
15.42 KB
Rename
Delete
ipaddr.rb
19.56 KB
Rename
Delete
irb.rb
22.53 KB
Rename
Delete
json.rb
1.77 KB
Rename
Delete
kconv.rb
5.77 KB
Rename
Delete
logger.rb
23.47 KB
Rename
Delete
matrix.rb
60.17 KB
Rename
Delete
mkmf.rb
84.87 KB
Rename
Delete
monitor.rb
7.87 KB
Rename
Delete
mutex_m.rb
2.16 KB
Rename
Delete
observer.rb
5.83 KB
Rename
Delete
open-uri.rb
25.13 KB
Rename
Delete
open3.rb
21.81 KB
Rename
Delete
openssl.rb
469 bytes
Rename
Delete
optionparser.rb
59 bytes
Rename
Delete
optparse.rb
57.74 KB
Rename
Delete
ostruct.rb
10.65 KB
Rename
Delete
pathname.rb
16.17 KB
Rename
Delete
pp.rb
15.08 KB
Rename
Delete
prettyprint.rb
15.89 KB
Rename
Delete
prime.rb
12.37 KB
Rename
Delete
profile.rb
235 bytes
Rename
Delete
profiler.rb
4.54 KB
Rename
Delete
pstore.rb
14.70 KB
Rename
Delete
psych.rb
21.11 KB
Rename
Delete
rdoc.rb
4.88 KB
Rename
Delete
resolv-replace.rb
1.76 KB
Rename
Delete
resolv.rb
73.44 KB
Rename
Delete
ripper.rb
2.44 KB
Rename
Delete
rss.rb
2.87 KB
Rename
Delete
rubygems.rb
36.11 KB
Rename
Delete
scanf.rb
23.55 KB
Rename
Delete
securerandom.rb
8.98 KB
Rename
Delete
set.rb
24.07 KB
Rename
Delete
shell.rb
11.39 KB
Rename
Delete
shellwords.rb
6.66 KB
Rename
Delete
singleton.rb
4.04 KB
Rename
Delete
socket.rb
43.51 KB
Rename
Delete
sync.rb
7.23 KB
Rename
Delete
tempfile.rb
11.21 KB
Rename
Delete
thwait.rb
3.33 KB
Rename
Delete
time.rb
23.56 KB
Rename
Delete
timeout.rb
3.81 KB
Rename
Delete
tmpdir.rb
4.25 KB
Rename
Delete
tracer.rb
6.42 KB
Rename
Delete
tsort.rb
14.30 KB
Rename
Delete
un.rb
9.95 KB
Rename
Delete
uri.rb
3.12 KB
Rename
Delete
weakref.rb
1.44 KB
Rename
Delete
webrick.rb
6.72 KB
Rename
Delete
yaml.rb
1.81 KB
Rename
Delete
# frozen_string_literal: true # Copyright (C) 2000 Network Applied Communication Laboratory, Inc. # Copyright (C) 2000 Information-technology Promotion Agency, Japan # Copyright (C) 2000-2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org> require 'continuation' if $SAFE > 0 STDERR.print "-r debug.rb is not available in safe mode\n" exit 1 end require 'tracer' require 'pp' class Tracer # :nodoc: def Tracer.trace_func(*vars) Single.trace_func(*vars) end end SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ # :nodoc: ## # This library provides debugging functionality to Ruby. # # To add a debugger to your code, start by requiring +debug+ in your # program: # # def say(word) # require 'debug' # puts word # end # # This will cause Ruby to interrupt execution and show a prompt when the +say+ # method is run. # # Once you're inside the prompt, you can start debugging your program. # # (rdb:1) p word # "hello" # # == Getting help # # You can get help at any time by pressing +h+. # # (rdb:1) h # Debugger help v.-0.002b # Commands # b[reak] [file:|class:]<line|method> # b[reak] [class.]<line|method> # set breakpoint to some position # wat[ch] <expression> set watchpoint to some expression # cat[ch] (<exception>|off) set catchpoint to an exception # b[reak] list breakpoints # cat[ch] show catchpoint # del[ete][ nnn] delete some or all breakpoints # disp[lay] <expression> add expression into display expression list # undisp[lay][ nnn] delete one particular or all display expressions # c[ont] run until program ends or hit breakpoint # s[tep][ nnn] step (into methods) one line or till line nnn # n[ext][ nnn] go over one line or till line nnn # w[here] display frames # f[rame] alias for where # l[ist][ (-|nn-mm)] list program, - lists backwards # nn-mm lists given lines # up[ nn] move to higher frame # down[ nn] move to lower frame # fin[ish] return to outer frame # tr[ace] (on|off) set trace mode of current thread # tr[ace] (on|off) all set trace mode of all threads # q[uit] exit from debugger # v[ar] g[lobal] show global variables # v[ar] l[ocal] show local variables # v[ar] i[nstance] <object> show instance variables of object # v[ar] c[onst] <object> show constants of object # m[ethod] i[nstance] <obj> show methods of object # m[ethod] <class|module> show instance methods of class or module # th[read] l[ist] list all threads # th[read] c[ur[rent]] show current thread # th[read] [sw[itch]] <nnn> switch thread context to nnn # th[read] stop <nnn> stop thread nnn # th[read] resume <nnn> resume thread nnn # p expression evaluate expression and print its value # h[elp] print this help # <everything else> evaluate # # == Usage # # The following is a list of common functionalities that the debugger # provides. # # === Navigating through your code # # In general, a debugger is used to find bugs in your program, which # often means pausing execution and inspecting variables at some point # in time. # # Let's look at an example: # # def my_method(foo) # require 'debug' # foo = get_foo if foo.nil? # raise if foo.nil? # end # # When you run this program, the debugger will kick in just before the # +foo+ assignment. # # (rdb:1) p foo # nil # # In this example, it'd be interesting to move to the next line and # inspect the value of +foo+ again. You can do that by pressing +n+: # # (rdb:1) n # goes to next line # (rdb:1) p foo # nil # # You now know that the original value of +foo+ was nil, and that it # still was nil after calling +get_foo+. # # Other useful commands for navigating through your code are: # # +c+:: # Runs the program until it either exists or encounters another breakpoint. # You usually press +c+ when you are finished debugging your program and # want to resume its execution. # +s+:: # Steps into method definition. In the previous example, +s+ would take you # inside the method definition of +get_foo+. # +r+:: # Restart the program. # +q+:: # Quit the program. # # === Inspecting variables # # You can use the debugger to easily inspect both local and global variables. # We've seen how to inspect local variables before: # # (rdb:1) p my_arg # 42 # # You can also pretty print the result of variables or expressions: # # (rdb:1) pp %w{a very long long array containing many words} # ["a", # "very", # "long", # ... # ] # # You can list all local variables with +v l+: # # (rdb:1) v l # foo => "hello" # # Similarly, you can show all global variables with +v g+: # # (rdb:1) v g # all global variables # # Finally, you can omit +p+ if you simply want to evaluate a variable or # expression # # (rdb:1) 5**2 # 25 # # === Going beyond basics # # Ruby Debug provides more advanced functionalities like switching # between threads, setting breakpoints and watch expressions, and more. # The full list of commands is available at any time by pressing +h+. # # == Staying out of trouble # # Make sure you remove every instance of +require 'debug'+ before # shipping your code. Failing to do so may result in your program # hanging unpredictably. # # Debug is not available in safe mode. class DEBUGGER__ MUTEX = Thread::Mutex.new # :nodoc: class Context # :nodoc: DEBUG_LAST_CMD = [] begin require 'readline' def readline(prompt, hist) Readline::readline(prompt, hist) end rescue LoadError def readline(prompt, hist) STDOUT.print prompt STDOUT.flush line = STDIN.gets exit unless line line.chomp! line end USE_READLINE = false end def initialize if Thread.current == Thread.main @stop_next = 1 else @stop_next = 0 end @last_file = nil @file = nil @line = nil @no_step = nil @frames = [] @finish_pos = 0 @trace = false @catch = "StandardError" @suspend_next = false end def stop_next(n=1) @stop_next = n end def set_suspend @suspend_next = true end def clear_suspend @suspend_next = false end def suspend_all DEBUGGER__.suspend end def resume_all DEBUGGER__.resume end def check_suspend while MUTEX.synchronize { if @suspend_next DEBUGGER__.waiting.push Thread.current @suspend_next = false true end } end end def trace? @trace end def set_trace(arg) @trace = arg end def stdout DEBUGGER__.stdout end def break_points DEBUGGER__.break_points end def display DEBUGGER__.display end def context(th) DEBUGGER__.context(th) end def set_trace_all(arg) DEBUGGER__.set_trace(arg) end def set_last_thread(th) DEBUGGER__.set_last_thread(th) end def debug_eval(str, binding) begin eval(str, binding) rescue StandardError, ScriptError => e at = eval("caller(1)", binding) stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '') for i in at stdout.printf "\tfrom %s\n", i end throw :debug_error end end def debug_silent_eval(str, binding) begin eval(str, binding) rescue StandardError, ScriptError nil end end def var_list(ary, binding) ary.sort! for v in ary stdout.printf " %s => %s\n", v, eval(v.to_s, binding).inspect end end def debug_variable_info(input, binding) case input when /^\s*g(?:lobal)?\s*$/ var_list(global_variables, binding) when /^\s*l(?:ocal)?\s*$/ var_list(eval("local_variables", binding), binding) when /^\s*i(?:nstance)?\s+/ obj = debug_eval($', binding) var_list(obj.instance_variables, obj.instance_eval{binding()}) when /^\s*c(?:onst(?:ant)?)?\s+/ obj = debug_eval($', binding) unless obj.kind_of? Module stdout.print "Should be Class/Module: ", $', "\n" else var_list(obj.constants, obj.module_eval{binding()}) end end end def debug_method_info(input, binding) case input when /^i(:?nstance)?\s+/ obj = debug_eval($', binding) len = 0 for v in obj.methods.sort len += v.size + 1 if len > 70 len = v.size + 1 stdout.print "\n" end stdout.print v, " " end stdout.print "\n" else obj = debug_eval(input, binding) unless obj.kind_of? Module stdout.print "Should be Class/Module: ", input, "\n" else len = 0 for v in obj.instance_methods(false).sort len += v.size + 1 if len > 70 len = v.size + 1 stdout.print "\n" end stdout.print v, " " end stdout.print "\n" end end end def thnum num = DEBUGGER__.instance_eval{@thread_list[Thread.current]} unless num DEBUGGER__.make_thread_list num = DEBUGGER__.instance_eval{@thread_list[Thread.current]} end num end def debug_command(file, line, id, binding) MUTEX.lock unless defined?($debugger_restart) and $debugger_restart callcc{|c| $debugger_restart = c} end set_last_thread(Thread.current) frame_pos = 0 binding_file = file binding_line = line previous_line = nil if ENV['EMACS'] stdout.printf "\032\032%s:%d:\n", binding_file, binding_line else stdout.printf "%s:%d:%s", binding_file, binding_line, line_at(binding_file, binding_line) end @frames[0] = [binding, file, line, id] display_expressions(binding) prompt = true while prompt and input = readline("(rdb:%d) "%thnum(), true) catch(:debug_error) do if input == "" next unless DEBUG_LAST_CMD[0] input = DEBUG_LAST_CMD[0] stdout.print input, "\n" else DEBUG_LAST_CMD[0] = input end case input when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/ if defined?( $2 ) if $1 == 'on' set_trace_all true else set_trace_all false end elsif defined?( $1 ) if $1 == 'on' set_trace true else set_trace false end end if trace? stdout.print "Trace on.\n" else stdout.print "Trace off.\n" end when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/ pos = $2 if $1 klass = debug_silent_eval($1, binding) file = $1 end if pos =~ /^\d+$/ pname = pos pos = pos.to_i else pname = pos = pos.intern.id2name end break_points.push [true, 0, klass || file, pos] stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/ pos = $2.intern.id2name klass = debug_eval($1, binding) break_points.push [true, 0, klass, pos] stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos when /^\s*wat(?:ch)?\s+(.+)$/ exp = $1 break_points.push [true, 1, exp] stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp when /^\s*b(?:reak)?$/ if break_points.find{|b| b[1] == 0} n = 1 stdout.print "Breakpoints:\n" break_points.each do |b| if b[0] and b[1] == 0 stdout.printf " %d %s:%s\n", n, b[2], b[3] end n += 1 end end if break_points.find{|b| b[1] == 1} n = 1 stdout.print "\n" stdout.print "Watchpoints:\n" for b in break_points if b[0] and b[1] == 1 stdout.printf " %d %s\n", n, b[2] end n += 1 end end if break_points.size == 0 stdout.print "No breakpoints\n" else stdout.print "\n" end when /^\s*del(?:ete)?(?:\s+(\d+))?$/ pos = $1 unless pos input = readline("Clear all breakpoints? (y/n) ", false) if input == "y" for b in break_points b[0] = false end end else pos = pos.to_i if break_points[pos-1] break_points[pos-1][0] = false else stdout.printf "Breakpoint %d is not defined\n", pos end end when /^\s*disp(?:lay)?\s+(.+)$/ exp = $1 display.push [true, exp] stdout.printf "%d: ", display.size display_expression(exp, binding) when /^\s*disp(?:lay)?$/ display_expressions(binding) when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/ pos = $1 unless pos input = readline("Clear all expressions? (y/n) ", false) if input == "y" for d in display d[0] = false end end else pos = pos.to_i if display[pos-1] display[pos-1][0] = false else stdout.printf "Display expression %d is not defined\n", pos end end when /^\s*c(?:ont)?$/ prompt = false when /^\s*s(?:tep)?(?:\s+(\d+))?$/ if $1 lev = $1.to_i else lev = 1 end @stop_next = lev prompt = false when /^\s*n(?:ext)?(?:\s+(\d+))?$/ if $1 lev = $1.to_i else lev = 1 end @stop_next = lev @no_step = @frames.size - frame_pos prompt = false when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/ display_frames(frame_pos) when /^\s*l(?:ist)?(?:\s+(.+))?$/ if not $1 b = previous_line ? previous_line + 10 : binding_line - 5 e = b + 9 elsif $1 == '-' b = previous_line ? previous_line - 10 : binding_line - 5 e = b + 9 else b, e = $1.split(/[-,]/) if e b = b.to_i e = e.to_i else b = b.to_i - 5 e = b + 9 end end previous_line = b display_list(b, e, binding_file, binding_line) when /^\s*up(?:\s+(\d+))?$/ previous_line = nil if $1 lev = $1.to_i else lev = 1 end frame_pos += lev if frame_pos >= @frames.size frame_pos = @frames.size - 1 stdout.print "At toplevel\n" end binding, binding_file, binding_line = @frames[frame_pos] stdout.print format_frame(frame_pos) when /^\s*down(?:\s+(\d+))?$/ previous_line = nil if $1 lev = $1.to_i else lev = 1 end frame_pos -= lev if frame_pos < 0 frame_pos = 0 stdout.print "At stack bottom\n" end binding, binding_file, binding_line = @frames[frame_pos] stdout.print format_frame(frame_pos) when /^\s*fin(?:ish)?$/ if frame_pos == @frames.size stdout.print "\"finish\" not meaningful in the outermost frame.\n" else @finish_pos = @frames.size - frame_pos frame_pos = 0 prompt = false end when /^\s*cat(?:ch)?(?:\s+(.+))?$/ if $1 excn = $1 if excn == 'off' @catch = nil stdout.print "Clear catchpoint.\n" else @catch = excn stdout.printf "Set catchpoint %s.\n", @catch end else if @catch stdout.printf "Catchpoint %s.\n", @catch else stdout.print "No catchpoint.\n" end end when /^\s*q(?:uit)?$/ input = readline("Really quit? (y/n) ", false) if input == "y" exit! # exit -> exit!: No graceful way to stop threads... end when /^\s*v(?:ar)?\s+/ debug_variable_info($', binding) when /^\s*m(?:ethod)?\s+/ debug_method_info($', binding) when /^\s*th(?:read)?\s+/ if DEBUGGER__.debug_thread_info($', binding) == :cont prompt = false end when /^\s*pp\s+/ PP.pp(debug_eval($', binding), stdout) when /^\s*p\s+/ stdout.printf "%s\n", debug_eval($', binding).inspect when /^\s*r(?:estart)?$/ $debugger_restart.call when /^\s*h(?:elp)?$/ debug_print_help() else v = debug_eval(input, binding) stdout.printf "%s\n", v.inspect end end end MUTEX.unlock resume_all end def debug_print_help stdout.print <<EOHELP Debugger help v.-0.002b Commands b[reak] [file:|class:]<line|method> b[reak] [class.]<line|method> set breakpoint to some position wat[ch] <expression> set watchpoint to some expression cat[ch] (<exception>|off) set catchpoint to an exception b[reak] list breakpoints cat[ch] show catchpoint del[ete][ nnn] delete some or all breakpoints disp[lay] <expression> add expression into display expression list undisp[lay][ nnn] delete one particular or all display expressions c[ont] run until program ends or hit breakpoint s[tep][ nnn] step (into methods) one line or till line nnn n[ext][ nnn] go over one line or till line nnn w[here] display frames f[rame] alias for where l[ist][ (-|nn-mm)] list program, - lists backwards nn-mm lists given lines up[ nn] move to higher frame down[ nn] move to lower frame fin[ish] return to outer frame tr[ace] (on|off) set trace mode of current thread tr[ace] (on|off) all set trace mode of all threads q[uit] exit from debugger v[ar] g[lobal] show global variables v[ar] l[ocal] show local variables v[ar] i[nstance] <object> show instance variables of object v[ar] c[onst] <object> show constants of object m[ethod] i[nstance] <obj> show methods of object m[ethod] <class|module> show instance methods of class or module th[read] l[ist] list all threads th[read] c[ur[rent]] show current thread th[read] [sw[itch]] <nnn> switch thread context to nnn th[read] stop <nnn> stop thread nnn th[read] resume <nnn> resume thread nnn pp expression evaluate expression and pretty_print its value p expression evaluate expression and print its value r[estart] restart program h[elp] print this help <everything else> evaluate EOHELP end def display_expressions(binding) n = 1 for d in display if d[0] stdout.printf "%d: ", n display_expression(d[1], binding) end n += 1 end end def display_expression(exp, binding) stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s end def frame_set_pos(file, line) if @frames[0] @frames[0][1] = file @frames[0][2] = line end end def display_frames(pos) 0.upto(@frames.size - 1) do |n| if n == pos stdout.print "--> " else stdout.print " " end stdout.print format_frame(n) end end def format_frame(pos) _, file, line, id = @frames[pos] sprintf "#%d %s:%s%s\n", pos + 1, file, line, (id ? ":in `#{id.id2name}'" : "") end def script_lines(file, line) unless (lines = SCRIPT_LINES__[file]) and lines != true Tracer::Single.get_line(file, line) if File.exist?(file) lines = SCRIPT_LINES__[file] lines = nil if lines == true end lines end def display_list(b, e, file, line) if lines = script_lines(file, line) stdout.printf "[%d, %d] in %s\n", b, e, file b.upto(e) do |n| if n > 0 && lines[n-1] if n == line stdout.printf "=> %d %s\n", n, lines[n-1].chomp else stdout.printf " %d %s\n", n, lines[n-1].chomp end end end else stdout.printf "No sourcefile available for %s\n", file end end def line_at(file, line) lines = script_lines(file, line) if lines and line = lines[line-1] return line end return "\n" end def debug_funcname(id) if id.nil? "toplevel" else id.id2name end end def check_break_points(file, klass, pos, binding, id) return false if break_points.empty? n = 1 for b in break_points if b[0] # valid if b[1] == 0 # breakpoint if (b[2] == file and b[3] == pos) or (klass and b[2] == klass and b[3] == pos) stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos return true end elsif b[1] == 1 # watchpoint if debug_silent_eval(b[2], binding) stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos return true end end end n += 1 end return false end def excn_handle(file, line, id, binding) if $!.class <= SystemExit set_trace_func nil exit end if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch }) stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class fs = @frames.size tb = caller(0)[-fs..-1] if tb for i in tb stdout.printf "\tfrom %s\n", i end end suspend_all debug_command(file, line, id, binding) end end def trace_func(event, file, line, id, binding, klass) Tracer.trace_func(event, file, line, id, binding, klass) if trace? context(Thread.current).check_suspend @file = file @line = line case event when 'line' frame_set_pos(file, line) if !@no_step or @frames.size == @no_step @stop_next -= 1 @stop_next = -1 if @stop_next < 0 elsif @frames.size < @no_step @stop_next = 0 # break here before leaving... else # nothing to do. skipped. end if @stop_next == 0 or check_break_points(file, nil, line, binding, id) @no_step = nil suspend_all debug_command(file, line, id, binding) end when 'call' @frames.unshift [binding, file, line, id] if check_break_points(file, klass, id.id2name, binding, id) suspend_all debug_command(file, line, id, binding) end when 'c-call' frame_set_pos(file, line) when 'class' @frames.unshift [binding, file, line, id] when 'return', 'end' if @frames.size == @finish_pos @stop_next = 1 @finish_pos = 0 end @frames.shift when 'raise' excn_handle(file, line, id, binding) end @last_file = file end end trap("INT") { DEBUGGER__.interrupt } @last_thread = Thread::main @max_thread = 1 @thread_list = {Thread::main => 1} @break_points = [] @display = [] @waiting = [] @stdout = STDOUT class << DEBUGGER__ # Returns the IO used as stdout. Defaults to STDOUT def stdout @stdout end # Sets the IO used as stdout. Defaults to STDOUT def stdout=(s) @stdout = s end # Returns the display expression list # # See DEBUGGER__ for more usage def display @display end # Returns the list of break points where execution will be stopped. # # See DEBUGGER__ for more usage def break_points @break_points end # Returns the list of waiting threads. # # When stepping through the traces of a function, thread gets suspended, to # be resumed later. def waiting @waiting end def set_trace( arg ) MUTEX.synchronize do make_thread_list for th, in @thread_list context(th).set_trace arg end end arg end def set_last_thread(th) @last_thread = th end def suspend MUTEX.synchronize do make_thread_list for th, in @thread_list next if th == Thread.current context(th).set_suspend end end # Schedule other threads to suspend as soon as possible. Thread.pass end def resume MUTEX.synchronize do make_thread_list @thread_list.each do |th,| next if th == Thread.current context(th).clear_suspend end waiting.each do |th| th.run end waiting.clear end # Schedule other threads to restart as soon as possible. Thread.pass end def context(thread=Thread.current) c = thread[:__debugger_data__] unless c thread[:__debugger_data__] = c = Context.new end c end def interrupt context(@last_thread).stop_next end def get_thread(num) th = @thread_list.key(num) unless th @stdout.print "No thread ##{num}\n" throw :debug_error end th end def thread_list(num) th = get_thread(num) if th == Thread.current @stdout.print "+" else @stdout.print " " end @stdout.printf "%d ", num @stdout.print th.inspect, "\t" file = context(th).instance_eval{@file} if file @stdout.print file,":",context(th).instance_eval{@line} end @stdout.print "\n" end # Prints all threads in @thread_list to @stdout. Returns a sorted array of # values from the @thread_list hash. # # While in the debugger you can list all of # the threads with: <b>DEBUGGER__.thread_list_all</b> # # (rdb:1) DEBUGGER__.thread_list_all # +1 #<Thread:0x007fb2320c03f0 run> debug_me.rb.rb:3 # 2 #<Thread:0x007fb23218a538@debug_me.rb.rb:3 sleep> # 3 #<Thread:0x007fb23218b0f0@debug_me.rb.rb:3 sleep> # [1, 2, 3] # # Your current thread is indicated by a <b>+</b> # # Additionally you can list all threads with <b>th l</b> # # (rdb:1) th l # +1 #<Thread:0x007f99328c0410 run> debug_me.rb:3 # 2 #<Thread:0x007f9932938230@debug_me.rb:3 sleep> debug_me.rb:3 # 3 #<Thread:0x007f9932938e10@debug_me.rb:3 sleep> debug_me.rb:3 # # See DEBUGGER__ for more usage. def thread_list_all for th in @thread_list.values.sort thread_list(th) end end def make_thread_list hash = {} for th in Thread::list if @thread_list.key? th hash[th] = @thread_list[th] else @max_thread += 1 hash[th] = @max_thread end end @thread_list = hash end def debug_thread_info(input, binding) case input when /^l(?:ist)?/ make_thread_list thread_list_all when /^c(?:ur(?:rent)?)?$/ make_thread_list thread_list(@thread_list[Thread.current]) when /^(?:sw(?:itch)?\s+)?(\d+)/ make_thread_list th = get_thread($1.to_i) if th == Thread.current @stdout.print "It's the current thread.\n" else thread_list(@thread_list[th]) context(th).stop_next th.run return :cont end when /^stop\s+(\d+)/ make_thread_list th = get_thread($1.to_i) if th == Thread.current @stdout.print "It's the current thread.\n" elsif th.stop? @stdout.print "Already stopped.\n" else thread_list(@thread_list[th]) context(th).suspend end when /^resume\s+(\d+)/ make_thread_list th = get_thread($1.to_i) if th == Thread.current @stdout.print "It's the current thread.\n" elsif !th.stop? @stdout.print "Already running." else thread_list(@thread_list[th]) th.run end end end end stdout.printf "Debug.rb\n" stdout.printf "Emacs support available.\n\n" RubyVM::InstructionSequence.compile_option = { trace_instruction: true } set_trace_func proc { |event, file, line, id, binding, klass, *rest| DEBUGGER__.context.trace_func event, file, line, id, binding, klass } end
Save