Hi, I am 'NaHi'. I sent mail to ruby-list several times, but am newbie here. I'm sorry for my poor English.(in advance :-) > From: GOTO Kentaro [mailto:gotoken / math.sci.hokudai.ac.jp] > Sent: Saturday, July 10, 1999 3:20 AM > >o Why is the -debug flag special? When writing/running a dynamically > > typed interactive program (like a gui), I *expect* errors, and > > getting a full, traversible stack trace with source file and line > > number information is *critical* (to me, at least). > > Well, a user can obtain trace stack by the global variable $@. > > > Shouldn't > > the debugger be part of the ruby core? > > I think it is partially right. The debugger, indeed, is not part of a > ruby interpreter. So, there exists degug.rb which is a gdb-like > debugger. > > % ruby -r debug yourcode.rb As gotoken-san saying, the debugger is not part of the interpreter, but has a few interfaces which supports debugging or tracing like set_trace_func(), caller(). You can see these used in debug.rb and trace.rb. And then, using debug.rb and trace.rb, ruby's debugging environment is powerful enough, I think. > In debug.rb prompt, The following is available command list. > > b(reak) Set breakpoint at specified line or function. set breakpoint at line nn -> 'b nn' at function foo -> 'b foo' at function bar in baz.rb -> 'b baz.rb:bar' see all breakpoint -> 'b(reak)' or 'info b(reak)' > i(nfo) Gotoken-san, I couldn't find it in debug.rb in ruby/1.3.4-990625... Old spec? for example, in ruby-1.2 or younger? > del(ete) [snip] > l(ist) > p Probably, of cource, Gotoken-san knows, 'p' is not a debug command but a ruby method. debug.rb keeps binding objects of each stack frame, and evaluate the unknown command in the suitable binding... ...(checking debug.rb by way of precaution)...Ah, that's not true! 'p' is certainly a debug command for putting value of then given command. I'm sorry... By the way, I made a patch since the action was more modeled on gdb. 'list' command lists just 10 line. 'list' command memorizes the line number listed before, for each target-file. 'list -' for listing previous 10 lines. 'list 0' does not cause error. 'up' and 'down' puts the stack frame where you are. # Although NaHi imitated Cle, NaHi don't know the meaning of '\' in a head. :-) \NaHi / / / Index: debug.rb =================================================================== RCS file: /home/cvs/ruby/lib/debug.rb,v retrieving revision 1.1.1.2.2.3 diff -u -r1.1.1.2.2.3 debug.rb --- debug.rb 1999/06/24 04:24:08 1.1.1.2.2.3 +++ debug.rb 1999/07/10 07:20:40 @@ -6,7 +6,7 @@ @break_points = [] @stop_next = 1 @frames = [nil] - @frame_pos = nil + @frame_pos = nil # nil means not '0' but `unknown'. @last_file = nil @scripts = {} end @@ -32,10 +32,14 @@ end def debug_command(file, line, id, binding) + binding_file = file + binding_line = line + debug_line = {} if (ENV['EMACS'] == 't') - printf "\032\032%s:%d:\n", file, line + printf "\032\032%s:%d:\n", binding_file, binding_line else - printf "%s:%d:%s", file, line, line_at(file, line) + printf "%s:%d:%s", binding_file, binding_line, + line_at(binding_file, binding_line) end @frames[-1] = binding STDOUT.print "(rdb:-) " @@ -120,9 +124,13 @@ @frame_pos -= lev if @frame_pos < 0 STDOUT.print "at toplevel\n" - @frame_pos = 0 + @frame_pos = nil else binding = @frames[@frame_pos] + frame_info = caller(4)[-(@frame_pos+1)] + STDOUT.print "at ", frame_info, "\n" + frame_info.sub( /:in `.*'$/, '' ) =~ /^(.*):(\d+)$/ + binding_file, binding_line = $1, $2.to_i end when /^down\s*(\d+)??$/ if $1 @@ -133,12 +141,16 @@ unless @frame_pos @frame_pos = @frames.size - 1 end - if lev >= @frames.size or @frame_pos and @frame_pos+lev >= @frames.size + @frame_pos += lev + if @frame_pos >= @frames.size STDOUT.print "at stack bottom\n" @frame_pos = nil else - @frame_pos += lev binding = @frames[@frame_pos] + frame_info = caller(4)[-(@frame_pos+1)] + STDOUT.print "at ", frame_info, "\n" + frame_info.sub( /:in `.*'$/, '' ) =~ /^(.*):(\d+)$/ + binding_file, binding_line = $1, $2.to_i end when /^fin(ish)?$/ @finish_pos = @frames.size @@ -154,29 +166,36 @@ printf " %s\n", i end when /^l(ist)?(\s+(.*))?$/ - if $3 + if !$3 + b = debug_line[binding_file]? debug_line[binding_file] + 10 : + binding_line - 5 + e = b + 9 + elsif $3 == '-' + b = debug_line[binding_file]? debug_line[binding_file] - 10 : + binding_line - 5 + e = b + 9 + else b, e = $3.split(/[-,]/) - b = Integer(b)-1 if e - e = Integer(e)-1 + b = Integer(b) + e = Integer(e) else - e = b + 10 + b = Integer(b)-5 + e = b + 9 end end - unless b - b = line - 1 - e = line + 9 - end - p [b,e] - line_at(file, line) - if lines = @scripts[file] and lines != TRUE - n = b+1 - for l in lines[b..e] - printf "%4d %s", n, l - n += 1 + debug_line[binding_file] = b + p [binding_file,b,e] + line_at(binding_file, binding_line) + if lines = @scripts[binding_file] and lines != TRUE + n = 0 + b.upto(e) do |n| + if n > 0 && lines[n-1] + printf "%4d %s\n", n, lines[n-1].chomp + end end else - printf "no sourcefile available for %s\n", file + printf "no sourcefile available for %s\n", binding_file end when /^p\s+/ p debug_eval($', binding) #'