From 0768eb098817fae08613f0492b89d6620f2c7d7c Mon Sep 17 00:00:00 2001 From: Mark Moseley Date: Tue, 21 Jul 2009 21:22:22 -0700 Subject: [PATCH] SVN RubyForge pull --- AUTHORS | 7 + CHANGES | 334 + ChangeLog | 5655 +++++++++++++++++ INSTALL.SVN | 154 + LICENSE | 23 + Makefile.am | 14 + Rakefile | 255 + autogen.sh | 4 + bin/.svn/README.txt | 2 + bin/.svn/empty-file | 0 bin/.svn/entries | 22 + bin/.svn/format | 1 + bin/.svn/prop-base/rdebug.svn-base | 5 + bin/.svn/props/rdebug.svn-work | 5 + bin/.svn/text-base/rdebug.svn-base | 415 ++ bin/rdebug | 415 ++ cli/.svn/README.txt | 2 + cli/.svn/empty-file | 0 cli/.svn/entries | 25 + cli/.svn/format | 1 + cli/.svn/prop-base/ruby-debug.rb.svn-base | 1 + cli/.svn/props/ruby-debug.rb.svn-work | 1 + cli/.svn/text-base/ruby-debug.rb.svn-base | 176 + cli/ruby-debug.rb | 176 + cli/ruby-debug/.svn/README.txt | 2 + cli/ruby-debug/.svn/empty-file | 0 cli/ruby-debug/.svn/entries | 61 + cli/ruby-debug/.svn/format | 1 + .../.svn/prop-base/command.rb.svn-base | 1 + .../.svn/prop-base/debugger.rb.svn-base | 1 + .../.svn/prop-base/helper.rb.svn-base | 1 + .../.svn/prop-base/interface.rb.svn-base | 1 + .../.svn/prop-base/processor.rb.svn-base | 1 + cli/ruby-debug/.svn/props/command.rb.svn-work | 1 + .../.svn/props/debugger.rb.svn-work | 1 + cli/ruby-debug/.svn/props/helper.rb.svn-work | 1 + .../.svn/props/interface.rb.svn-work | 1 + .../.svn/props/processor.rb.svn-work | 1 + .../.svn/text-base/command.rb.svn-base | 228 + .../.svn/text-base/debugger.rb.svn-base | 5 + .../.svn/text-base/helper.rb.svn-base | 69 + .../.svn/text-base/interface.rb.svn-base | 232 + .../.svn/text-base/processor.rb.svn-base | 474 ++ cli/ruby-debug/command.rb | 228 + cli/ruby-debug/commands/.svn/README.txt | 2 + cli/ruby-debug/commands/.svn/empty-file | 0 cli/ruby-debug/commands/.svn/entries | 265 + cli/ruby-debug/commands/.svn/format | 1 + .../.svn/prop-base/breakpoints.rb.svn-base | 1 + .../.svn/prop-base/catchpoint.rb.svn-base | 1 + .../.svn/prop-base/condition.rb.svn-base | 1 + .../.svn/prop-base/continue.rb.svn-base | 1 + .../.svn/prop-base/control.rb.svn-base | 1 + .../.svn/prop-base/display.rb.svn-base | 1 + .../commands/.svn/prop-base/edit.rb.svn-base | 1 + .../.svn/prop-base/enable.rb.svn-base | 1 + .../commands/.svn/prop-base/eval.rb.svn-base | 1 + .../.svn/prop-base/finish.rb.svn-base | 1 + .../commands/.svn/prop-base/frame.rb.svn-base | 1 + .../commands/.svn/prop-base/help.rb.svn-base | 1 + .../commands/.svn/prop-base/info.rb.svn-base | 1 + .../commands/.svn/prop-base/irb.rb.svn-base | 1 + .../commands/.svn/prop-base/kill.rb.svn-base | 5 + .../commands/.svn/prop-base/list.rb.svn-base | 1 + .../.svn/prop-base/method.rb.svn-base | 1 + .../commands/.svn/prop-base/quit.rb.svn-base | 1 + .../.svn/prop-base/reload.rb.svn-base | 1 + .../commands/.svn/prop-base/save.rb.svn-base | 1 + .../commands/.svn/prop-base/set.rb.svn-base | 1 + .../commands/.svn/prop-base/show.rb.svn-base | 1 + .../.svn/prop-base/source.rb.svn-base | 1 + .../.svn/prop-base/stepping.rb.svn-base | 1 + .../.svn/prop-base/threads.rb.svn-base | 1 + .../commands/.svn/prop-base/tmate.rb.svn-base | 1 + .../commands/.svn/prop-base/trace.rb.svn-base | 1 + .../.svn/prop-base/variables.rb.svn-base | 1 + .../.svn/props/breakpoints.rb.svn-work | 1 + .../.svn/props/catchpoint.rb.svn-work | 1 + .../commands/.svn/props/condition.rb.svn-work | 1 + .../commands/.svn/props/continue.rb.svn-work | 1 + .../commands/.svn/props/control.rb.svn-work | 1 + .../commands/.svn/props/display.rb.svn-work | 1 + .../commands/.svn/props/edit.rb.svn-work | 1 + .../commands/.svn/props/enable.rb.svn-work | 1 + .../commands/.svn/props/eval.rb.svn-work | 1 + .../commands/.svn/props/finish.rb.svn-work | 1 + .../commands/.svn/props/frame.rb.svn-work | 1 + .../commands/.svn/props/help.rb.svn-work | 1 + .../commands/.svn/props/info.rb.svn-work | 1 + .../commands/.svn/props/irb.rb.svn-work | 1 + .../commands/.svn/props/kill.rb.svn-work | 5 + .../commands/.svn/props/list.rb.svn-work | 1 + .../commands/.svn/props/method.rb.svn-work | 1 + .../commands/.svn/props/quit.rb.svn-work | 1 + .../commands/.svn/props/reload.rb.svn-work | 1 + .../commands/.svn/props/save.rb.svn-work | 1 + .../commands/.svn/props/set.rb.svn-work | 1 + .../commands/.svn/props/show.rb.svn-work | 1 + .../commands/.svn/props/source.rb.svn-work | 1 + .../commands/.svn/props/stepping.rb.svn-work | 1 + .../commands/.svn/props/threads.rb.svn-work | 1 + .../commands/.svn/props/tmate.rb.svn-work | 1 + .../commands/.svn/props/trace.rb.svn-work | 1 + .../commands/.svn/props/variables.rb.svn-work | 1 + .../.svn/text-base/breakpoints.rb.svn-base | 153 + .../.svn/text-base/catchpoint.rb.svn-base | 55 + .../.svn/text-base/condition.rb.svn-base | 49 + .../.svn/text-base/continue.rb.svn-base | 38 + .../.svn/text-base/control.rb.svn-base | 107 + .../.svn/text-base/display.rb.svn-base | 120 + .../commands/.svn/text-base/edit.rb.svn-base | 48 + .../.svn/text-base/enable.rb.svn-base | 202 + .../commands/.svn/text-base/eval.rb.svn-base | 176 + .../.svn/text-base/finish.rb.svn-base | 42 + .../commands/.svn/text-base/frame.rb.svn-base | 301 + .../commands/.svn/text-base/help.rb.svn-base | 56 + .../commands/.svn/text-base/info.rb.svn-base | 469 ++ .../commands/.svn/text-base/irb.rb.svn-base | 123 + .../commands/.svn/text-base/kill.rb.svn-base | 51 + .../commands/.svn/text-base/list.rb.svn-base | 94 + .../.svn/text-base/method.rb.svn-base | 84 + .../commands/.svn/text-base/quit.rb.svn-base | 39 + .../.svn/text-base/reload.rb.svn-base | 40 + .../commands/.svn/text-base/save.rb.svn-base | 90 + .../commands/.svn/text-base/set.rb.svn-base | 237 + .../commands/.svn/text-base/show.rb.svn-base | 253 + .../.svn/text-base/source.rb.svn-base | 36 + .../.svn/text-base/stepping.rb.svn-base | 81 + .../.svn/text-base/threads.rb.svn-base | 189 + .../commands/.svn/text-base/tmate.rb.svn-base | 36 + .../commands/.svn/text-base/trace.rb.svn-base | 57 + .../.svn/text-base/variables.rb.svn-base | 199 + cli/ruby-debug/commands/breakpoints.rb | 153 + cli/ruby-debug/commands/catchpoint.rb | 55 + cli/ruby-debug/commands/condition.rb | 49 + cli/ruby-debug/commands/continue.rb | 38 + cli/ruby-debug/commands/control.rb | 107 + cli/ruby-debug/commands/display.rb | 120 + cli/ruby-debug/commands/edit.rb | 48 + cli/ruby-debug/commands/enable.rb | 202 + cli/ruby-debug/commands/eval.rb | 176 + cli/ruby-debug/commands/finish.rb | 42 + cli/ruby-debug/commands/frame.rb | 301 + cli/ruby-debug/commands/help.rb | 56 + cli/ruby-debug/commands/info.rb | 469 ++ cli/ruby-debug/commands/irb.rb | 123 + cli/ruby-debug/commands/kill.rb | 51 + cli/ruby-debug/commands/list.rb | 94 + cli/ruby-debug/commands/method.rb | 84 + cli/ruby-debug/commands/quit.rb | 39 + cli/ruby-debug/commands/reload.rb | 40 + cli/ruby-debug/commands/save.rb | 90 + cli/ruby-debug/commands/set.rb | 237 + cli/ruby-debug/commands/show.rb | 253 + cli/ruby-debug/commands/source.rb | 36 + cli/ruby-debug/commands/stepping.rb | 81 + cli/ruby-debug/commands/threads.rb | 189 + cli/ruby-debug/commands/tmate.rb | 36 + cli/ruby-debug/commands/trace.rb | 57 + cli/ruby-debug/commands/variables.rb | 199 + cli/ruby-debug/debugger.rb | 5 + cli/ruby-debug/helper.rb | 69 + cli/ruby-debug/interface.rb | 232 + cli/ruby-debug/processor.rb | 474 ++ configure.ac | 12 + doc/.cvsignore | 42 + doc/.svn/README.txt | 2 + doc/.svn/dir-prop-base | 47 + doc/.svn/dir-props | 47 + doc/.svn/empty-file | 0 doc/.svn/entries | 113 + doc/.svn/format | 1 + doc/.svn/prop-base/.cvsignore.svn-base | 1 + doc/.svn/prop-base/Makefile.am.svn-base | 1 + doc/.svn/prop-base/emacs-notes.txt.svn-base | 1 + doc/.svn/prop-base/hanoi.rb.svn-base | 1 + doc/.svn/prop-base/primes.rb.svn-base | 1 + doc/.svn/prop-base/rdebug-emacs.texi.svn-base | 1 + doc/.svn/prop-base/rdebug.1.svn-base | 5 + doc/.svn/prop-base/ruby-debug.texi.svn-base | 1 + doc/.svn/prop-base/test-tri2.rb.svn-base | 1 + doc/.svn/prop-base/tri3.rb.svn-base | 1 + doc/.svn/prop-base/triangle.rb.svn-base | 1 + doc/.svn/props/.cvsignore.svn-work | 1 + doc/.svn/props/Makefile.am.svn-work | 1 + doc/.svn/props/emacs-notes.txt.svn-work | 1 + doc/.svn/props/hanoi.rb.svn-work | 1 + doc/.svn/props/primes.rb.svn-work | 1 + doc/.svn/props/rdebug-emacs.texi.svn-work | 1 + doc/.svn/props/rdebug.1.svn-work | 5 + doc/.svn/props/ruby-debug.texi.svn-work | 1 + doc/.svn/props/test-tri2.rb.svn-work | 1 + doc/.svn/props/tri3.rb.svn-work | 1 + doc/.svn/props/triangle.rb.svn-work | 1 + doc/.svn/text-base/.cvsignore.svn-base | 42 + doc/.svn/text-base/Makefile.am.svn-base | 63 + doc/.svn/text-base/emacs-notes.txt.svn-base | 38 + doc/.svn/text-base/hanoi.rb.svn-base | 35 + doc/.svn/text-base/primes.rb.svn-base | 28 + doc/.svn/text-base/rdebug-emacs.texi.svn-base | 1030 +++ doc/.svn/text-base/rdebug.1.svn-base | 241 + doc/.svn/text-base/ruby-debug.texi.svn-base | 3982 ++++++++++++ doc/.svn/text-base/test-tri2.rb.svn-base | 18 + doc/.svn/text-base/tri3.rb.svn-base | 8 + doc/.svn/text-base/triangle.rb.svn-base | 12 + doc/Makefile.am | 63 + doc/emacs-notes.txt | 38 + doc/hanoi.rb | 35 + doc/primes.rb | 28 + doc/rdebug-emacs.texi | 1030 +++ doc/rdebug.1 | 241 + doc/ruby-debug.texi | 3982 ++++++++++++ doc/test-tri2.rb | 18 + doc/tri3.rb | 8 + doc/triangle.rb | 12 + emacs/.svn/README.txt | 2 + emacs/.svn/dir-prop-base | 10 + emacs/.svn/dir-props | 10 + emacs/.svn/empty-file | 0 emacs/.svn/entries | 233 + emacs/.svn/format | 1 + emacs/.svn/prop-base/Makefile.am.svn-base | 1 + .../prop-base/rdebug-annotate.el.svn-base | 5 + .../.svn/prop-base/rdebug-breaks.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-cmd.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-core.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-dbg.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-error.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-fns.el.svn-base | 1 + .../.svn/prop-base/rdebug-frames.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-gud.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-help.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-info.el.svn-base | 1 + .../.svn/prop-base/rdebug-layouts.el.svn-base | 5 + .../.svn/prop-base/rdebug-locring.el.svn-base | 5 + .../.svn/prop-base/rdebug-output.el.svn-base | 5 + .../.svn/prop-base/rdebug-regexp.el.svn-base | 5 + .../prop-base/rdebug-secondary.el.svn-base | 5 + .../prop-base/rdebug-shortkey.el.svn-base | 5 + .../.svn/prop-base/rdebug-source.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-track.el.svn-base | 5 + .../.svn/prop-base/rdebug-varbuf.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-vars.el.svn-base | 5 + emacs/.svn/prop-base/rdebug-watch.el.svn-base | 5 + emacs/.svn/prop-base/rdebug.el.svn-base | 1 + emacs/.svn/props/Makefile.am.svn-work | 1 + emacs/.svn/props/rdebug-annotate.el.svn-work | 5 + emacs/.svn/props/rdebug-breaks.el.svn-work | 5 + emacs/.svn/props/rdebug-cmd.el.svn-work | 5 + emacs/.svn/props/rdebug-core.el.svn-work | 5 + emacs/.svn/props/rdebug-dbg.el.svn-work | 5 + emacs/.svn/props/rdebug-error.el.svn-work | 5 + emacs/.svn/props/rdebug-fns.el.svn-work | 1 + emacs/.svn/props/rdebug-frames.el.svn-work | 5 + emacs/.svn/props/rdebug-gud.el.svn-work | 5 + emacs/.svn/props/rdebug-help.el.svn-work | 5 + emacs/.svn/props/rdebug-info.el.svn-work | 1 + emacs/.svn/props/rdebug-layouts.el.svn-work | 5 + emacs/.svn/props/rdebug-locring.el.svn-work | 5 + emacs/.svn/props/rdebug-output.el.svn-work | 5 + emacs/.svn/props/rdebug-regexp.el.svn-work | 5 + emacs/.svn/props/rdebug-secondary.el.svn-work | 5 + emacs/.svn/props/rdebug-shortkey.el.svn-work | 5 + emacs/.svn/props/rdebug-source.el.svn-work | 5 + emacs/.svn/props/rdebug-track.el.svn-work | 5 + emacs/.svn/props/rdebug-varbuf.el.svn-work | 5 + emacs/.svn/props/rdebug-vars.el.svn-work | 5 + emacs/.svn/props/rdebug-watch.el.svn-work | 5 + emacs/.svn/props/rdebug.el.svn-work | 1 + emacs/.svn/text-base/Makefile.am.svn-base | 130 + .../text-base/rdebug-annotate.el.svn-base | 385 ++ .../.svn/text-base/rdebug-breaks.el.svn-base | 407 ++ emacs/.svn/text-base/rdebug-cmd.el.svn-base | 92 + emacs/.svn/text-base/rdebug-core.el.svn-base | 502 ++ emacs/.svn/text-base/rdebug-dbg.el.svn-base | 62 + emacs/.svn/text-base/rdebug-error.el.svn-base | 79 + emacs/.svn/text-base/rdebug-fns.el.svn-base | 111 + .../.svn/text-base/rdebug-frames.el.svn-base | 230 + emacs/.svn/text-base/rdebug-gud.el.svn-base | 242 + emacs/.svn/text-base/rdebug-help.el.svn-base | 104 + emacs/.svn/text-base/rdebug-info.el.svn-base | 83 + .../.svn/text-base/rdebug-layouts.el.svn-base | 180 + .../.svn/text-base/rdebug-locring.el.svn-base | 118 + .../.svn/text-base/rdebug-output.el.svn-base | 106 + .../.svn/text-base/rdebug-regexp.el.svn-base | 118 + .../text-base/rdebug-secondary.el.svn-base | 260 + .../text-base/rdebug-shortkey.el.svn-base | 175 + .../.svn/text-base/rdebug-source.el.svn-base | 568 ++ emacs/.svn/text-base/rdebug-track.el.svn-base | 392 ++ .../.svn/text-base/rdebug-varbuf.el.svn-base | 150 + emacs/.svn/text-base/rdebug-vars.el.svn-base | 125 + emacs/.svn/text-base/rdebug-watch.el.svn-base | 132 + emacs/.svn/text-base/rdebug.el.svn-base | 326 + emacs/Makefile.am | 130 + emacs/rdebug-annotate.el | 385 ++ emacs/rdebug-breaks.el | 407 ++ emacs/rdebug-cmd.el | 92 + emacs/rdebug-core.el | 502 ++ emacs/rdebug-dbg.el | 62 + emacs/rdebug-error.el | 79 + emacs/rdebug-fns.el | 111 + emacs/rdebug-frames.el | 230 + emacs/rdebug-gud.el | 242 + emacs/rdebug-help.el | 104 + emacs/rdebug-info.el | 83 + emacs/rdebug-layouts.el | 180 + emacs/rdebug-locring.el | 118 + emacs/rdebug-output.el | 106 + emacs/rdebug-regexp.el | 118 + emacs/rdebug-secondary.el | 260 + emacs/rdebug-shortkey.el | 175 + emacs/rdebug-source.el | 568 ++ emacs/rdebug-track.el | 392 ++ emacs/rdebug-varbuf.el | 150 + emacs/rdebug-vars.el | 125 + emacs/rdebug-watch.el | 132 + emacs/rdebug.el | 326 + emacs/test/.svn/README.txt | 2 + emacs/test/.svn/empty-file | 0 emacs/test/.svn/entries | 103 + emacs/test/.svn/format | 1 + .../test/.svn/prop-base/elk-test.el.svn-base | 1 + .../.svn/prop-base/test-annotate.el.svn-base | 1 + .../test/.svn/prop-base/test-cmd.el.svn-base | 1 + .../test/.svn/prop-base/test-core.el.svn-base | 1 + .../test/.svn/prop-base/test-fns.el.svn-base | 1 + .../.svn/prop-base/test-frames.el.svn-base | 1 + .../test/.svn/prop-base/test-gud.el.svn-base | 1 + .../.svn/prop-base/test-indent.el.svn-base | 1 + .../.svn/prop-base/test-regexp.el.svn-base | 1 + .../.svn/prop-base/test-shortkey.el.svn-base | 1 + emacs/test/.svn/props/elk-test.el.svn-work | 1 + .../test/.svn/props/test-annotate.el.svn-work | 1 + emacs/test/.svn/props/test-cmd.el.svn-work | 1 + emacs/test/.svn/props/test-core.el.svn-work | 1 + emacs/test/.svn/props/test-fns.el.svn-work | 1 + emacs/test/.svn/props/test-frames.el.svn-work | 1 + emacs/test/.svn/props/test-gud.el.svn-work | 1 + emacs/test/.svn/props/test-indent.el.svn-work | 1 + emacs/test/.svn/props/test-regexp.el.svn-work | 1 + .../test/.svn/props/test-shortkey.el.svn-work | 1 + .../test/.svn/text-base/elk-test.el.svn-base | 242 + .../.svn/text-base/test-annotate.el.svn-base | 103 + .../test/.svn/text-base/test-cmd.el.svn-base | 116 + .../test/.svn/text-base/test-core.el.svn-base | 104 + .../test/.svn/text-base/test-fns.el.svn-base | 65 + .../.svn/text-base/test-frames.el.svn-base | 62 + .../test/.svn/text-base/test-gud.el.svn-base | 35 + .../.svn/text-base/test-indent.el.svn-base | 58 + .../.svn/text-base/test-regexp.el.svn-base | 144 + .../.svn/text-base/test-shortkey.el.svn-base | 61 + emacs/test/elk-test.el | 242 + emacs/test/test-annotate.el | 103 + emacs/test/test-cmd.el | 116 + emacs/test/test-core.el | 104 + emacs/test/test-fns.el | 65 + emacs/test/test-frames.el | 62 + emacs/test/test-gud.el | 35 + emacs/test/test-indent.el | 58 + emacs/test/test-regexp.el | 144 + emacs/test/test-shortkey.el | 61 + ext/.svn/README.txt | 2 + ext/.svn/dir-prop-base | 8 + ext/.svn/dir-props | 8 + ext/.svn/empty-file | 0 ext/.svn/entries | 53 + ext/.svn/format | 1 + ext/.svn/prop-base/breakpoint.c.svn-base | 1 + ext/.svn/prop-base/extconf.rb.svn-base | 1 + ext/.svn/prop-base/ruby_debug.c.svn-base | 1 + ext/.svn/prop-base/ruby_debug.h.svn-base | 1 + ext/.svn/props/breakpoint.c.svn-work | 1 + ext/.svn/props/extconf.rb.svn-work | 1 + ext/.svn/props/ruby_debug.c.svn-work | 1 + ext/.svn/props/ruby_debug.h.svn-work | 1 + ext/.svn/text-base/breakpoint.c.svn-base | 579 ++ ext/.svn/text-base/extconf.rb.svn-base | 20 + ext/.svn/text-base/ruby_debug.c.svn-base | 2322 +++++++ ext/.svn/text-base/ruby_debug.h.svn-base | 123 + ext/breakpoint.c | 579 ++ ext/extconf.rb | 20 + ext/ruby_debug.c | 2322 +++++++ ext/ruby_debug.h | 123 + ext/win32/.cvsignore | 3 + ext/win32/.svn/README.txt | 2 + ext/win32/.svn/dir-prop-base | 8 + ext/win32/.svn/dir-props | 8 + ext/win32/.svn/empty-file | 0 ext/win32/.svn/entries | 23 + ext/win32/.svn/format | 1 + ext/win32/.svn/prop-base/.cvsignore.svn-base | 1 + ext/win32/.svn/props/.cvsignore.svn-work | 1 + ext/win32/.svn/text-base/.cvsignore.svn-base | 3 + lib/.svn/README.txt | 2 + lib/.svn/empty-file | 0 lib/.svn/entries | 31 + lib/.svn/format | 1 + lib/.svn/prop-base/ChangeLog.svn-base | 1 + .../prop-base/ruby-debug-base.rb.svn-base | 1 + lib/.svn/props/ChangeLog.svn-work | 1 + lib/.svn/props/ruby-debug-base.rb.svn-work | 1 + lib/.svn/text-base/ChangeLog.svn-base | 1065 ++++ .../text-base/ruby-debug-base.rb.svn-base | 298 + lib/ChangeLog | 1065 ++++ lib/ruby-debug-base.rb | 298 + rdbg.rb | 33 + runner.sh | 7 + svn2cl_usermap | 3 + test/.cvsignore | 1 + test/.svn/README.txt | 2 + test/.svn/dir-prop-base | 6 + test/.svn/dir-props | 6 + test/.svn/empty-file | 0 test/.svn/entries | 491 ++ test/.svn/format | 1 + test/.svn/prop-base/.cvsignore.svn-base | 1 + test/.svn/prop-base/bp_loop_issue.rb.svn-base | 1 + test/.svn/prop-base/classes.rb.svn-base | 1 + test/.svn/prop-base/config.yaml.svn-base | 1 + test/.svn/prop-base/dollar-0.rb.svn-base | 9 + test/.svn/prop-base/gcd-dbg-nox.rb.svn-base | 1 + test/.svn/prop-base/gcd-dbg.rb.svn-base | 5 + test/.svn/prop-base/gcd.rb.svn-base | 1 + test/.svn/prop-base/helper.rb.svn-base | 1 + test/.svn/prop-base/info-var-bug.rb.svn-base | 1 + test/.svn/prop-base/info-var-bug2.rb.svn-base | 1 + test/.svn/prop-base/null.rb.svn-base | 1 + test/.svn/prop-base/output.rb.svn-base | 1 + test/.svn/prop-base/pm-base.rb.svn-base | 5 + test/.svn/prop-base/pm-bug.rb.svn-base | 1 + test/.svn/prop-base/pm.rb.svn-base | 5 + test/.svn/prop-base/raise.rb.svn-base | 5 + test/.svn/prop-base/rdebug-save.1.svn-base | 1 + test/.svn/prop-base/runall.svn-base | 5 + test/.svn/prop-base/tdebug.rb.svn-base | 5 + test/.svn/prop-base/test-annotate.rb.svn-base | 5 + .../.svn/prop-base/test-break-bad.rb.svn-base | 5 + .../prop-base/test-breakpoints.rb.svn-base | 5 + test/.svn/prop-base/test-catch.rb.svn-base | 5 + .../.svn/prop-base/test-condition.rb.svn-base | 5 + test/.svn/prop-base/test-ctrl.rb.svn-base | 5 + test/.svn/prop-base/test-display.rb.svn-base | 5 + test/.svn/prop-base/test-dollar-0.rb.svn-base | 5 + test/.svn/prop-base/test-edit.rb.svn-base | 5 + .../prop-base/test-emacs-basic.rb.svn-base | 5 + test/.svn/prop-base/test-enable.rb.svn-base | 5 + test/.svn/prop-base/test-finish.rb.svn-base | 5 + test/.svn/prop-base/test-frame.rb.svn-base | 5 + test/.svn/prop-base/test-help.rb.svn-base | 5 + test/.svn/prop-base/test-hist.rb.svn-base | 5 + .../prop-base/test-info-thread.rb.svn-base | 5 + test/.svn/prop-base/test-info-var.rb.svn-base | 5 + test/.svn/prop-base/test-info.rb.svn-base | 5 + test/.svn/prop-base/test-init.rb.svn-base | 5 + test/.svn/prop-base/test-list.rb.svn-base | 5 + test/.svn/prop-base/test-method.rb.svn-base | 5 + test/.svn/prop-base/test-output.rb.svn-base | 5 + test/.svn/prop-base/test-pm.rb.svn-base | 5 + test/.svn/prop-base/test-quit.rb.svn-base | 5 + test/.svn/prop-base/test-raise.rb.svn-base | 5 + test/.svn/prop-base/test-save.rb.svn-base | 5 + test/.svn/prop-base/test-setshow.rb.svn-base | 5 + test/.svn/prop-base/test-source.rb.svn-base | 5 + test/.svn/prop-base/test-stepping.rb.svn-base | 5 + test/.svn/prop-base/test-trace.rb.svn-base | 5 + test/.svn/prop-base/thread1.rb.svn-base | 1 + test/.svn/prop-base/trunc-call.rb.svn-base | 1 + test/.svn/props/.cvsignore.svn-work | 1 + test/.svn/props/bp_loop_issue.rb.svn-work | 1 + test/.svn/props/classes.rb.svn-work | 1 + test/.svn/props/config.yaml.svn-work | 1 + test/.svn/props/dollar-0.rb.svn-work | 9 + test/.svn/props/gcd-dbg-nox.rb.svn-work | 1 + test/.svn/props/gcd-dbg.rb.svn-work | 5 + test/.svn/props/gcd.rb.svn-work | 1 + test/.svn/props/helper.rb.svn-work | 1 + test/.svn/props/info-var-bug.rb.svn-work | 1 + test/.svn/props/info-var-bug2.rb.svn-work | 1 + test/.svn/props/null.rb.svn-work | 1 + test/.svn/props/output.rb.svn-work | 1 + test/.svn/props/pm-base.rb.svn-work | 5 + test/.svn/props/pm-bug.rb.svn-work | 1 + test/.svn/props/pm.rb.svn-work | 5 + test/.svn/props/raise.rb.svn-work | 5 + test/.svn/props/rdebug-save.1.svn-work | 1 + test/.svn/props/runall.svn-work | 5 + test/.svn/props/tdebug.rb.svn-work | 5 + test/.svn/props/test-annotate.rb.svn-work | 5 + test/.svn/props/test-break-bad.rb.svn-work | 5 + test/.svn/props/test-breakpoints.rb.svn-work | 5 + test/.svn/props/test-catch.rb.svn-work | 5 + test/.svn/props/test-condition.rb.svn-work | 5 + test/.svn/props/test-ctrl.rb.svn-work | 5 + test/.svn/props/test-display.rb.svn-work | 5 + test/.svn/props/test-dollar-0.rb.svn-work | 5 + test/.svn/props/test-edit.rb.svn-work | 5 + test/.svn/props/test-emacs-basic.rb.svn-work | 5 + test/.svn/props/test-enable.rb.svn-work | 5 + test/.svn/props/test-finish.rb.svn-work | 5 + test/.svn/props/test-frame.rb.svn-work | 5 + test/.svn/props/test-help.rb.svn-work | 5 + test/.svn/props/test-hist.rb.svn-work | 5 + test/.svn/props/test-info-thread.rb.svn-work | 5 + test/.svn/props/test-info-var.rb.svn-work | 5 + test/.svn/props/test-info.rb.svn-work | 5 + test/.svn/props/test-init.rb.svn-work | 5 + test/.svn/props/test-list.rb.svn-work | 5 + test/.svn/props/test-method.rb.svn-work | 5 + test/.svn/props/test-output.rb.svn-work | 5 + test/.svn/props/test-pm.rb.svn-work | 5 + test/.svn/props/test-quit.rb.svn-work | 5 + test/.svn/props/test-raise.rb.svn-work | 5 + test/.svn/props/test-save.rb.svn-work | 5 + test/.svn/props/test-setshow.rb.svn-work | 5 + test/.svn/props/test-source.rb.svn-work | 5 + test/.svn/props/test-stepping.rb.svn-work | 5 + test/.svn/props/test-trace.rb.svn-work | 5 + test/.svn/props/thread1.rb.svn-work | 1 + test/.svn/props/trunc-call.rb.svn-work | 1 + test/.svn/text-base/.cvsignore.svn-base | 1 + test/.svn/text-base/bp_loop_issue.rb.svn-base | 3 + test/.svn/text-base/classes.rb.svn-base | 11 + test/.svn/text-base/config.yaml.svn-base | 8 + test/.svn/text-base/dollar-0.rb.svn-base | 5 + test/.svn/text-base/gcd-dbg-nox.rb.svn-base | 31 + test/.svn/text-base/gcd-dbg.rb.svn-base | 30 + test/.svn/text-base/gcd.rb.svn-base | 18 + test/.svn/text-base/helper.rb.svn-base | 143 + test/.svn/text-base/info-var-bug.rb.svn-base | 47 + test/.svn/text-base/info-var-bug2.rb.svn-base | 2 + test/.svn/text-base/null.rb.svn-base | 1 + test/.svn/text-base/output.rb.svn-base | 2 + test/.svn/text-base/pm-base.rb.svn-base | 22 + test/.svn/text-base/pm-bug.rb.svn-base | 3 + test/.svn/text-base/pm.rb.svn-base | 11 + test/.svn/text-base/raise.rb.svn-base | 3 + test/.svn/text-base/rdebug-save.1.svn-base | 7 + test/.svn/text-base/runall.svn-base | 12 + test/.svn/text-base/tdebug.rb.svn-base | 252 + test/.svn/text-base/test-annotate.rb.svn-base | 25 + .../.svn/text-base/test-break-bad.rb.svn-base | 36 + .../text-base/test-breakpoints.rb.svn-base | 25 + test/.svn/text-base/test-catch.rb.svn-base | 25 + .../.svn/text-base/test-condition.rb.svn-base | 25 + test/.svn/text-base/test-ctrl.rb.svn-base | 55 + test/.svn/text-base/test-display.rb.svn-base | 26 + test/.svn/text-base/test-dollar-0.rb.svn-base | 45 + test/.svn/text-base/test-edit.rb.svn-base | 26 + .../text-base/test-emacs-basic.rb.svn-base | 26 + test/.svn/text-base/test-enable.rb.svn-base | 25 + test/.svn/text-base/test-finish.rb.svn-base | 34 + test/.svn/text-base/test-frame.rb.svn-base | 34 + test/.svn/text-base/test-help.rb.svn-base | 60 + test/.svn/text-base/test-hist.rb.svn-base | 68 + .../text-base/test-info-thread.rb.svn-base | 32 + test/.svn/text-base/test-info-var.rb.svn-base | 47 + test/.svn/text-base/test-info.rb.svn-base | 26 + test/.svn/text-base/test-init.rb.svn-base | 43 + test/.svn/text-base/test-list.rb.svn-base | 25 + test/.svn/text-base/test-method.rb.svn-base | 34 + test/.svn/text-base/test-output.rb.svn-base | 26 + test/.svn/text-base/test-pm.rb.svn-base | 59 + test/.svn/text-base/test-quit.rb.svn-base | 30 + test/.svn/text-base/test-raise.rb.svn-base | 25 + test/.svn/text-base/test-save.rb.svn-base | 31 + test/.svn/text-base/test-setshow.rb.svn-base | 25 + test/.svn/text-base/test-source.rb.svn-base | 25 + test/.svn/text-base/test-stepping.rb.svn-base | 26 + test/.svn/text-base/test-trace.rb.svn-base | 63 + test/.svn/text-base/thread1.rb.svn-base | 26 + test/.svn/text-base/trunc-call.rb.svn-base | 31 + test/base/.svn/README.txt | 2 + test/base/.svn/empty-file | 0 test/base/.svn/entries | 49 + test/base/.svn/format | 1 + test/base/.svn/prop-base/base.rb.svn-base | 5 + test/base/.svn/prop-base/binding.rb.svn-base | 5 + .../.svn/prop-base/catchpoint.rb.svn-base | 5 + test/base/.svn/prop-base/load.rb.svn-base | 1 + test/base/.svn/props/base.rb.svn-work | 5 + test/base/.svn/props/binding.rb.svn-work | 5 + test/base/.svn/props/catchpoint.rb.svn-work | 5 + test/base/.svn/props/load.rb.svn-work | 1 + test/base/.svn/text-base/base.rb.svn-base | 74 + test/base/.svn/text-base/binding.rb.svn-base | 31 + .../.svn/text-base/catchpoint.rb.svn-base | 26 + test/base/.svn/text-base/load.rb.svn-base | 40 + test/base/base.rb | 74 + test/base/binding.rb | 31 + test/base/catchpoint.rb | 26 + test/base/load.rb | 40 + test/bp_loop_issue.rb | 3 + test/classes.rb | 11 + test/cli/.svn/README.txt | 2 + test/cli/.svn/empty-file | 0 test/cli/.svn/entries | 16 + test/cli/.svn/format | 1 + test/cli/commands/.svn/README.txt | 2 + test/cli/commands/.svn/empty-file | 0 test/cli/commands/.svn/entries | 25 + test/cli/commands/.svn/format | 1 + .../prop-base/catchpoint_test.rb.svn-base | 1 + .../.svn/props/catchpoint_test.rb.svn-work | 1 + .../text-base/catchpoint_test.rb.svn-base | 36 + test/cli/commands/catchpoint_test.rb | 36 + test/cli/commands/unit/.svn/README.txt | 2 + test/cli/commands/unit/.svn/empty-file | 0 test/cli/commands/unit/.svn/entries | 22 + test/cli/commands/unit/.svn/format | 1 + .../unit/.svn/prop-base/regexp.rb.svn-base | 1 + .../unit/.svn/props/regexp.rb.svn-work | 1 + .../unit/.svn/text-base/regexp.rb.svn-base | 42 + test/cli/commands/unit/regexp.rb | 42 + test/config.yaml | 8 + test/data/.svn/README.txt | 2 + test/data/.svn/empty-file | 0 test/data/.svn/entries | 697 ++ test/data/.svn/format | 1 + .../data/.svn/prop-base/annotate.cmd.svn-base | 1 + .../.svn/prop-base/annotate.right.svn-base | 1 + .../.svn/prop-base/break_bad.cmd.svn-base | 1 + .../.svn/prop-base/break_bad.right.svn-base | 1 + .../prop-base/break_loop_bug.cmd.svn-base | 1 + .../prop-base/break_loop_bug.right.svn-base | 1 + .../.svn/prop-base/breakpoints.cmd.svn-base | 1 + .../.svn/prop-base/breakpoints.right.svn-base | 1 + test/data/.svn/prop-base/catch.cmd.svn-base | 1 + test/data/.svn/prop-base/catch.right.svn-base | 1 + .../.svn/prop-base/condition.cmd.svn-base | 1 + .../.svn/prop-base/condition.right.svn-base | 1 + test/data/.svn/prop-base/ctrl.cmd.svn-base | 1 + test/data/.svn/prop-base/ctrl.right.svn-base | 1 + test/data/.svn/prop-base/display.cmd.svn-base | 1 + .../.svn/prop-base/display.right.svn-base | 1 + .../.svn/prop-base/dollar-0.right.svn-base | 1 + .../.svn/prop-base/dollar-0a.right.svn-base | 1 + .../.svn/prop-base/dollar-0b.right.svn-base | 1 + test/data/.svn/prop-base/edit.cmd.svn-base | 1 + test/data/.svn/prop-base/edit.right.svn-base | 1 + .../.svn/prop-base/emacs_basic.cmd.svn-base | 1 + .../.svn/prop-base/emacs_basic.right.svn-base | 1 + test/data/.svn/prop-base/enable.cmd.svn-base | 1 + .../data/.svn/prop-base/enable.right.svn-base | 1 + test/data/.svn/prop-base/finish.cmd.svn-base | 1 + .../data/.svn/prop-base/finish.right.svn-base | 1 + test/data/.svn/prop-base/frame.cmd.svn-base | 1 + test/data/.svn/prop-base/frame.right.svn-base | 1 + test/data/.svn/prop-base/help.cmd.svn-base | 1 + test/data/.svn/prop-base/help.right.svn-base | 1 + .../.svn/prop-base/history.right.svn-base | 1 + .../.svn/prop-base/info-thread.cmd.svn-base | 1 + .../.svn/prop-base/info-thread.right.svn-base | 1 + .../.svn/prop-base/info-var-bug2.cmd.svn-base | 1 + .../prop-base/info-var-bug2.right.svn-base | 1 + .../data/.svn/prop-base/info-var.cmd.svn-base | 1 + .../.svn/prop-base/info-var.right.svn-base | 1 + test/data/.svn/prop-base/info.cmd.svn-base | 1 + test/data/.svn/prop-base/info.right.svn-base | 1 + .../.svn/prop-base/linetrace.cmd.svn-base | 1 + .../.svn/prop-base/linetrace.right.svn-base | 1 + .../.svn/prop-base/linetracep.cmd.svn-base | 1 + .../.svn/prop-base/linetracep.right.svn-base | 1 + test/data/.svn/prop-base/list.cmd.svn-base | 1 + test/data/.svn/prop-base/list.right.svn-base | 1 + test/data/.svn/prop-base/method.cmd.svn-base | 1 + .../data/.svn/prop-base/method.right.svn-base | 1 + .../.svn/prop-base/methodsig.cmd.svn-base | 1 + .../.svn/prop-base/methodsig.right.svn-base | 1 + .../data/.svn/prop-base/noquit.right.svn-base | 1 + test/data/.svn/prop-base/output.cmd.svn-base | 1 + .../data/.svn/prop-base/output.right.svn-base | 1 + test/data/.svn/prop-base/pm-bug.cmd.svn-base | 1 + .../data/.svn/prop-base/pm-bug.right.svn-base | 1 + .../prop-base/post-mortem-next.cmd.svn-base | 1 + .../prop-base/post-mortem-next.right.svn-base | 1 + .../prop-base/post-mortem-osx.right.svn-base | 1 + .../.svn/prop-base/post-mortem.cmd.svn-base | 1 + .../.svn/prop-base/post-mortem.right.svn-base | 1 + test/data/.svn/prop-base/quit.cmd.svn-base | 1 + test/data/.svn/prop-base/quit.right.svn-base | 1 + test/data/.svn/prop-base/raise.cmd.svn-base | 1 + test/data/.svn/prop-base/raise.right.svn-base | 1 + test/data/.svn/prop-base/save.cmd.svn-base | 1 + test/data/.svn/prop-base/save.right.svn-base | 1 + test/data/.svn/prop-base/setshow.cmd.svn-base | 5 + .../.svn/prop-base/setshow.right.svn-base | 1 + test/data/.svn/prop-base/source.cmd.svn-base | 1 + .../data/.svn/prop-base/source.right.svn-base | 1 + .../data/.svn/prop-base/stepping.cmd.svn-base | 1 + .../.svn/prop-base/stepping.right.svn-base | 1 + .../prop-base/test-init-cygwin.right.svn-base | 1 + .../prop-base/test-init-osx.right.svn-base | 1 + .../.svn/prop-base/test-init.right.svn-base | 1 + test/data/.svn/prop-base/trace.right.svn-base | 1 + test/data/.svn/props/annotate.cmd.svn-work | 1 + test/data/.svn/props/annotate.right.svn-work | 1 + test/data/.svn/props/break_bad.cmd.svn-work | 1 + test/data/.svn/props/break_bad.right.svn-work | 1 + .../.svn/props/break_loop_bug.cmd.svn-work | 1 + .../.svn/props/break_loop_bug.right.svn-work | 1 + test/data/.svn/props/breakpoints.cmd.svn-work | 1 + .../.svn/props/breakpoints.right.svn-work | 1 + test/data/.svn/props/catch.cmd.svn-work | 1 + test/data/.svn/props/catch.right.svn-work | 1 + test/data/.svn/props/condition.cmd.svn-work | 1 + test/data/.svn/props/condition.right.svn-work | 1 + test/data/.svn/props/ctrl.cmd.svn-work | 1 + test/data/.svn/props/ctrl.right.svn-work | 1 + test/data/.svn/props/display.cmd.svn-work | 1 + test/data/.svn/props/display.right.svn-work | 1 + test/data/.svn/props/dollar-0.right.svn-work | 1 + test/data/.svn/props/dollar-0a.right.svn-work | 1 + test/data/.svn/props/dollar-0b.right.svn-work | 1 + test/data/.svn/props/edit.cmd.svn-work | 1 + test/data/.svn/props/edit.right.svn-work | 1 + test/data/.svn/props/emacs_basic.cmd.svn-work | 1 + .../.svn/props/emacs_basic.right.svn-work | 1 + test/data/.svn/props/enable.cmd.svn-work | 1 + test/data/.svn/props/enable.right.svn-work | 1 + test/data/.svn/props/finish.cmd.svn-work | 1 + test/data/.svn/props/finish.right.svn-work | 1 + test/data/.svn/props/frame.cmd.svn-work | 1 + test/data/.svn/props/frame.right.svn-work | 1 + test/data/.svn/props/help.cmd.svn-work | 1 + test/data/.svn/props/help.right.svn-work | 1 + test/data/.svn/props/history.right.svn-work | 1 + test/data/.svn/props/info-thread.cmd.svn-work | 1 + .../.svn/props/info-thread.right.svn-work | 1 + .../.svn/props/info-var-bug2.cmd.svn-work | 1 + .../.svn/props/info-var-bug2.right.svn-work | 1 + test/data/.svn/props/info-var.cmd.svn-work | 1 + test/data/.svn/props/info-var.right.svn-work | 1 + test/data/.svn/props/info.cmd.svn-work | 1 + test/data/.svn/props/info.right.svn-work | 1 + test/data/.svn/props/linetrace.cmd.svn-work | 1 + test/data/.svn/props/linetrace.right.svn-work | 1 + test/data/.svn/props/linetracep.cmd.svn-work | 1 + .../data/.svn/props/linetracep.right.svn-work | 1 + test/data/.svn/props/list.cmd.svn-work | 1 + test/data/.svn/props/list.right.svn-work | 1 + test/data/.svn/props/method.cmd.svn-work | 1 + test/data/.svn/props/method.right.svn-work | 1 + test/data/.svn/props/methodsig.cmd.svn-work | 1 + test/data/.svn/props/methodsig.right.svn-work | 1 + test/data/.svn/props/noquit.right.svn-work | 1 + test/data/.svn/props/output.cmd.svn-work | 1 + test/data/.svn/props/output.right.svn-work | 1 + test/data/.svn/props/pm-bug.cmd.svn-work | 1 + test/data/.svn/props/pm-bug.right.svn-work | 1 + .../.svn/props/post-mortem-next.cmd.svn-work | 1 + .../props/post-mortem-next.right.svn-work | 1 + .../.svn/props/post-mortem-osx.right.svn-work | 1 + test/data/.svn/props/post-mortem.cmd.svn-work | 1 + .../.svn/props/post-mortem.right.svn-work | 1 + test/data/.svn/props/quit.cmd.svn-work | 1 + test/data/.svn/props/quit.right.svn-work | 1 + test/data/.svn/props/raise.cmd.svn-work | 1 + test/data/.svn/props/raise.right.svn-work | 1 + test/data/.svn/props/save.cmd.svn-work | 1 + test/data/.svn/props/save.right.svn-work | 1 + test/data/.svn/props/setshow.cmd.svn-work | 5 + test/data/.svn/props/setshow.right.svn-work | 1 + test/data/.svn/props/source.cmd.svn-work | 1 + test/data/.svn/props/source.right.svn-work | 1 + test/data/.svn/props/stepping.cmd.svn-work | 1 + test/data/.svn/props/stepping.right.svn-work | 1 + .../props/test-init-cygwin.right.svn-work | 1 + .../.svn/props/test-init-osx.right.svn-work | 1 + test/data/.svn/props/test-init.right.svn-work | 1 + test/data/.svn/props/trace.right.svn-work | 1 + .../data/.svn/text-base/annotate.cmd.svn-base | 29 + .../.svn/text-base/annotate.right.svn-base | 139 + .../.svn/text-base/break_bad.cmd.svn-base | 18 + .../.svn/text-base/break_bad.right.svn-base | 28 + .../text-base/break_loop_bug.cmd.svn-base | 5 + .../text-base/break_loop_bug.right.svn-base | 15 + .../.svn/text-base/breakpoints.cmd.svn-base | 38 + .../.svn/text-base/breakpoints.right.svn-base | 98 + test/data/.svn/text-base/catch.cmd.svn-base | 17 + test/data/.svn/text-base/catch.right.svn-base | 37 + .../.svn/text-base/condition.cmd.svn-base | 28 + .../.svn/text-base/condition.right.svn-base | 65 + test/data/.svn/text-base/ctrl.cmd.svn-base | 23 + test/data/.svn/text-base/ctrl.right.svn-base | 69 + test/data/.svn/text-base/display.cmd.svn-base | 24 + .../.svn/text-base/display.right.svn-base | 44 + .../.svn/text-base/dollar-0.right.svn-base | 2 + .../.svn/text-base/dollar-0a.right.svn-base | 2 + .../.svn/text-base/dollar-0b.right.svn-base | 2 + test/data/.svn/text-base/edit.cmd.svn-base | 12 + test/data/.svn/text-base/edit.right.svn-base | 19 + .../.svn/text-base/emacs_basic.cmd.svn-base | 43 + .../.svn/text-base/emacs_basic.right.svn-base | 106 + test/data/.svn/text-base/enable.cmd.svn-base | 20 + .../data/.svn/text-base/enable.right.svn-base | 36 + test/data/.svn/text-base/finish.cmd.svn-base | 16 + .../data/.svn/text-base/finish.right.svn-base | 31 + test/data/.svn/text-base/frame.cmd.svn-base | 26 + test/data/.svn/text-base/frame.right.svn-base | 55 + test/data/.svn/text-base/help.cmd.svn-base | 20 + test/data/.svn/text-base/help.right.svn-base | 21 + .../.svn/text-base/history.right.svn-base | 7 + .../.svn/text-base/info-thread.cmd.svn-base | 13 + .../.svn/text-base/info-thread.right.svn-base | 37 + .../.svn/text-base/info-var-bug2.cmd.svn-base | 5 + .../text-base/info-var-bug2.right.svn-base | 10 + .../data/.svn/text-base/info-var.cmd.svn-base | 23 + .../.svn/text-base/info-var.right.svn-base | 52 + test/data/.svn/text-base/info.cmd.svn-base | 21 + test/data/.svn/text-base/info.right.svn-base | 65 + .../.svn/text-base/linetrace.cmd.svn-base | 6 + .../.svn/text-base/linetrace.right.svn-base | 32 + .../.svn/text-base/linetracep.cmd.svn-base | 7 + .../.svn/text-base/linetracep.right.svn-base | 25 + test/data/.svn/text-base/list.cmd.svn-base | 19 + test/data/.svn/text-base/list.right.svn-base | 127 + test/data/.svn/text-base/method.cmd.svn-base | 10 + .../data/.svn/text-base/method.right.svn-base | 21 + .../.svn/text-base/methodsig.cmd.svn-base | 10 + .../.svn/text-base/methodsig.right.svn-base | 20 + .../data/.svn/text-base/noquit.right.svn-base | 1 + test/data/.svn/text-base/output.cmd.svn-base | 6 + .../data/.svn/text-base/output.right.svn-base | 31 + test/data/.svn/text-base/pm-bug.cmd.svn-base | 7 + .../data/.svn/text-base/pm-bug.right.svn-base | 12 + .../text-base/post-mortem-next.cmd.svn-base | 8 + .../text-base/post-mortem-next.right.svn-base | 14 + .../text-base/post-mortem-osx.right.svn-base | 31 + .../.svn/text-base/post-mortem.cmd.svn-base | 13 + .../.svn/text-base/post-mortem.right.svn-base | 32 + test/data/.svn/text-base/quit.cmd.svn-base | 6 + test/data/.svn/text-base/quit.right.svn-base | 0 test/data/.svn/text-base/raise.cmd.svn-base | 11 + test/data/.svn/text-base/raise.right.svn-base | 26 + test/data/.svn/text-base/save.cmd.svn-base | 33 + test/data/.svn/text-base/save.right.svn-base | 59 + test/data/.svn/text-base/setshow.cmd.svn-base | 56 + .../.svn/text-base/setshow.right.svn-base | 97 + test/data/.svn/text-base/source.cmd.svn-base | 5 + .../data/.svn/text-base/source.right.svn-base | 15 + .../data/.svn/text-base/stepping.cmd.svn-base | 21 + .../.svn/text-base/stepping.right.svn-base | 50 + .../text-base/test-init-cygwin.right.svn-base | 7 + .../text-base/test-init-osx.right.svn-base | 4 + .../.svn/text-base/test-init.right.svn-base | 5 + test/data/.svn/text-base/trace.right.svn-base | 23 + test/data/annotate.cmd | 29 + test/data/annotate.right | 139 + test/data/break_bad.cmd | 18 + test/data/break_bad.right | 28 + test/data/break_loop_bug.cmd | 5 + test/data/break_loop_bug.right | 15 + test/data/breakpoints.cmd | 38 + test/data/breakpoints.right | 98 + test/data/catch.cmd | 17 + test/data/catch.right | 37 + test/data/condition.cmd | 28 + test/data/condition.right | 65 + test/data/ctrl.cmd | 23 + test/data/ctrl.right | 69 + test/data/display.cmd | 24 + test/data/display.right | 44 + test/data/dollar-0.right | 2 + test/data/dollar-0a.right | 2 + test/data/dollar-0b.right | 2 + test/data/edit.cmd | 12 + test/data/edit.right | 19 + test/data/emacs_basic.cmd | 43 + test/data/emacs_basic.right | 106 + test/data/enable.cmd | 20 + test/data/enable.right | 36 + test/data/finish.cmd | 16 + test/data/finish.right | 31 + test/data/frame.cmd | 26 + test/data/frame.right | 55 + test/data/help.cmd | 20 + test/data/help.right | 21 + test/data/history.right | 7 + test/data/info-thread.cmd | 13 + test/data/info-thread.right | 37 + test/data/info-var-bug2.cmd | 5 + test/data/info-var-bug2.right | 10 + test/data/info-var.cmd | 23 + test/data/info-var.right | 52 + test/data/info.cmd | 21 + test/data/info.right | 65 + test/data/linetrace.cmd | 6 + test/data/linetrace.right | 32 + test/data/linetracep.cmd | 7 + test/data/linetracep.right | 25 + test/data/list.cmd | 19 + test/data/list.right | 127 + test/data/method.cmd | 10 + test/data/method.right | 21 + test/data/methodsig.cmd | 10 + test/data/methodsig.right | 20 + test/data/noquit.right | 1 + test/data/output.cmd | 6 + test/data/output.right | 31 + test/data/pm-bug.cmd | 7 + test/data/pm-bug.right | 12 + test/data/post-mortem-next.cmd | 8 + test/data/post-mortem-next.right | 14 + test/data/post-mortem-osx.right | 31 + test/data/post-mortem.cmd | 13 + test/data/post-mortem.right | 32 + test/data/quit.cmd | 6 + test/data/quit.right | 0 test/data/raise.cmd | 11 + test/data/raise.right | 26 + test/data/save.cmd | 33 + test/data/save.right | 59 + test/data/setshow.cmd | 56 + test/data/setshow.right | 97 + test/data/source.cmd | 5 + test/data/source.right | 15 + test/data/stepping.cmd | 21 + test/data/stepping.right | 50 + test/data/test-init-cygwin.right | 7 + test/data/test-init-osx.right | 4 + test/data/test-init.right | 5 + test/data/trace.right | 23 + test/dollar-0.rb | 5 + test/gcd-dbg-nox.rb | 31 + test/gcd-dbg.rb | 30 + test/gcd.rb | 18 + test/helper.rb | 143 + test/info-var-bug.rb | 47 + test/info-var-bug2.rb | 2 + test/null.rb | 1 + test/output.rb | 2 + test/pm-base.rb | 22 + test/pm-bug.rb | 3 + test/pm.rb | 11 + test/raise.rb | 3 + test/rdebug-save.1 | 7 + test/runall | 12 + test/tdebug.rb | 252 + test/test-annotate.rb | 25 + test/test-break-bad.rb | 36 + test/test-breakpoints.rb | 25 + test/test-catch.rb | 25 + test/test-condition.rb | 25 + test/test-ctrl.rb | 55 + test/test-display.rb | 26 + test/test-dollar-0.rb | 45 + test/test-edit.rb | 26 + test/test-emacs-basic.rb | 26 + test/test-enable.rb | 25 + test/test-finish.rb | 34 + test/test-frame.rb | 34 + test/test-help.rb | 60 + test/test-hist.rb | 68 + test/test-info-thread.rb | 32 + test/test-info-var.rb | 47 + test/test-info.rb | 26 + test/test-init.rb | 43 + test/test-list.rb | 25 + test/test-method.rb | 34 + test/test-output.rb | 26 + test/test-pm.rb | 59 + test/test-quit.rb | 30 + test/test-raise.rb | 25 + test/test-save.rb | 31 + test/test-setshow.rb | 25 + test/test-source.rb | 25 + test/test-stepping.rb | 26 + test/test-trace.rb | 63 + test/thread1.rb | 26 + test/trunc-call.rb | 31 + 970 files changed, 60176 insertions(+) create mode 100644 AUTHORS create mode 100644 CHANGES create mode 100644 ChangeLog create mode 100644 INSTALL.SVN create mode 100644 LICENSE create mode 100644 Makefile.am create mode 100644 Rakefile create mode 100755 autogen.sh create mode 100644 bin/.svn/README.txt create mode 100644 bin/.svn/empty-file create mode 100644 bin/.svn/entries create mode 100644 bin/.svn/format create mode 100644 bin/.svn/prop-base/rdebug.svn-base create mode 100644 bin/.svn/props/rdebug.svn-work create mode 100644 bin/.svn/text-base/rdebug.svn-base create mode 100755 bin/rdebug create mode 100644 cli/.svn/README.txt create mode 100644 cli/.svn/empty-file create mode 100644 cli/.svn/entries create mode 100644 cli/.svn/format create mode 100644 cli/.svn/prop-base/ruby-debug.rb.svn-base create mode 100644 cli/.svn/props/ruby-debug.rb.svn-work create mode 100644 cli/.svn/text-base/ruby-debug.rb.svn-base create mode 100644 cli/ruby-debug.rb create mode 100644 cli/ruby-debug/.svn/README.txt create mode 100644 cli/ruby-debug/.svn/empty-file create mode 100644 cli/ruby-debug/.svn/entries create mode 100644 cli/ruby-debug/.svn/format create mode 100644 cli/ruby-debug/.svn/prop-base/command.rb.svn-base create mode 100644 cli/ruby-debug/.svn/prop-base/debugger.rb.svn-base create mode 100644 cli/ruby-debug/.svn/prop-base/helper.rb.svn-base create mode 100644 cli/ruby-debug/.svn/prop-base/interface.rb.svn-base create mode 100644 cli/ruby-debug/.svn/prop-base/processor.rb.svn-base create mode 100644 cli/ruby-debug/.svn/props/command.rb.svn-work create mode 100644 cli/ruby-debug/.svn/props/debugger.rb.svn-work create mode 100644 cli/ruby-debug/.svn/props/helper.rb.svn-work create mode 100644 cli/ruby-debug/.svn/props/interface.rb.svn-work create mode 100644 cli/ruby-debug/.svn/props/processor.rb.svn-work create mode 100644 cli/ruby-debug/.svn/text-base/command.rb.svn-base create mode 100644 cli/ruby-debug/.svn/text-base/debugger.rb.svn-base create mode 100644 cli/ruby-debug/.svn/text-base/helper.rb.svn-base create mode 100644 cli/ruby-debug/.svn/text-base/interface.rb.svn-base create mode 100644 cli/ruby-debug/.svn/text-base/processor.rb.svn-base create mode 100644 cli/ruby-debug/command.rb create mode 100644 cli/ruby-debug/commands/.svn/README.txt create mode 100644 cli/ruby-debug/commands/.svn/empty-file create mode 100644 cli/ruby-debug/commands/.svn/entries create mode 100644 cli/ruby-debug/commands/.svn/format create mode 100644 cli/ruby-debug/commands/.svn/prop-base/breakpoints.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/catchpoint.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/condition.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/continue.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/control.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/display.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/edit.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/enable.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/eval.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/finish.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/frame.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/help.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/info.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/irb.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/kill.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/list.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/method.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/quit.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/reload.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/save.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/set.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/show.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/source.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/stepping.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/threads.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/tmate.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/trace.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/prop-base/variables.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/props/breakpoints.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/catchpoint.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/condition.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/continue.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/control.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/display.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/edit.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/enable.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/eval.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/finish.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/frame.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/help.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/info.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/irb.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/kill.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/list.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/method.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/quit.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/reload.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/save.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/set.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/show.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/source.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/stepping.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/threads.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/tmate.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/trace.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/props/variables.rb.svn-work create mode 100644 cli/ruby-debug/commands/.svn/text-base/breakpoints.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/catchpoint.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/condition.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/continue.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/control.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/display.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/edit.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/enable.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/eval.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/finish.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/frame.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/help.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/info.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/irb.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/kill.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/list.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/method.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/quit.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/reload.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/save.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/set.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/show.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/source.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/stepping.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/threads.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/tmate.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/trace.rb.svn-base create mode 100644 cli/ruby-debug/commands/.svn/text-base/variables.rb.svn-base create mode 100644 cli/ruby-debug/commands/breakpoints.rb create mode 100644 cli/ruby-debug/commands/catchpoint.rb create mode 100644 cli/ruby-debug/commands/condition.rb create mode 100644 cli/ruby-debug/commands/continue.rb create mode 100644 cli/ruby-debug/commands/control.rb create mode 100644 cli/ruby-debug/commands/display.rb create mode 100644 cli/ruby-debug/commands/edit.rb create mode 100644 cli/ruby-debug/commands/enable.rb create mode 100644 cli/ruby-debug/commands/eval.rb create mode 100644 cli/ruby-debug/commands/finish.rb create mode 100644 cli/ruby-debug/commands/frame.rb create mode 100644 cli/ruby-debug/commands/help.rb create mode 100644 cli/ruby-debug/commands/info.rb create mode 100644 cli/ruby-debug/commands/irb.rb create mode 100644 cli/ruby-debug/commands/kill.rb create mode 100644 cli/ruby-debug/commands/list.rb create mode 100644 cli/ruby-debug/commands/method.rb create mode 100644 cli/ruby-debug/commands/quit.rb create mode 100644 cli/ruby-debug/commands/reload.rb create mode 100644 cli/ruby-debug/commands/save.rb create mode 100644 cli/ruby-debug/commands/set.rb create mode 100644 cli/ruby-debug/commands/show.rb create mode 100644 cli/ruby-debug/commands/source.rb create mode 100644 cli/ruby-debug/commands/stepping.rb create mode 100644 cli/ruby-debug/commands/threads.rb create mode 100644 cli/ruby-debug/commands/tmate.rb create mode 100644 cli/ruby-debug/commands/trace.rb create mode 100644 cli/ruby-debug/commands/variables.rb create mode 100644 cli/ruby-debug/debugger.rb create mode 100644 cli/ruby-debug/helper.rb create mode 100644 cli/ruby-debug/interface.rb create mode 100644 cli/ruby-debug/processor.rb create mode 100644 configure.ac create mode 100644 doc/.cvsignore create mode 100644 doc/.svn/README.txt create mode 100644 doc/.svn/dir-prop-base create mode 100644 doc/.svn/dir-props create mode 100644 doc/.svn/empty-file create mode 100644 doc/.svn/entries create mode 100644 doc/.svn/format create mode 100644 doc/.svn/prop-base/.cvsignore.svn-base create mode 100644 doc/.svn/prop-base/Makefile.am.svn-base create mode 100644 doc/.svn/prop-base/emacs-notes.txt.svn-base create mode 100644 doc/.svn/prop-base/hanoi.rb.svn-base create mode 100644 doc/.svn/prop-base/primes.rb.svn-base create mode 100644 doc/.svn/prop-base/rdebug-emacs.texi.svn-base create mode 100644 doc/.svn/prop-base/rdebug.1.svn-base create mode 100644 doc/.svn/prop-base/ruby-debug.texi.svn-base create mode 100644 doc/.svn/prop-base/test-tri2.rb.svn-base create mode 100644 doc/.svn/prop-base/tri3.rb.svn-base create mode 100644 doc/.svn/prop-base/triangle.rb.svn-base create mode 100644 doc/.svn/props/.cvsignore.svn-work create mode 100644 doc/.svn/props/Makefile.am.svn-work create mode 100644 doc/.svn/props/emacs-notes.txt.svn-work create mode 100644 doc/.svn/props/hanoi.rb.svn-work create mode 100644 doc/.svn/props/primes.rb.svn-work create mode 100644 doc/.svn/props/rdebug-emacs.texi.svn-work create mode 100644 doc/.svn/props/rdebug.1.svn-work create mode 100644 doc/.svn/props/ruby-debug.texi.svn-work create mode 100644 doc/.svn/props/test-tri2.rb.svn-work create mode 100644 doc/.svn/props/tri3.rb.svn-work create mode 100644 doc/.svn/props/triangle.rb.svn-work create mode 100644 doc/.svn/text-base/.cvsignore.svn-base create mode 100644 doc/.svn/text-base/Makefile.am.svn-base create mode 100644 doc/.svn/text-base/emacs-notes.txt.svn-base create mode 100644 doc/.svn/text-base/hanoi.rb.svn-base create mode 100644 doc/.svn/text-base/primes.rb.svn-base create mode 100644 doc/.svn/text-base/rdebug-emacs.texi.svn-base create mode 100644 doc/.svn/text-base/rdebug.1.svn-base create mode 100644 doc/.svn/text-base/ruby-debug.texi.svn-base create mode 100644 doc/.svn/text-base/test-tri2.rb.svn-base create mode 100644 doc/.svn/text-base/tri3.rb.svn-base create mode 100644 doc/.svn/text-base/triangle.rb.svn-base create mode 100644 doc/Makefile.am create mode 100644 doc/emacs-notes.txt create mode 100644 doc/hanoi.rb create mode 100644 doc/primes.rb create mode 100644 doc/rdebug-emacs.texi create mode 100644 doc/rdebug.1 create mode 100644 doc/ruby-debug.texi create mode 100644 doc/test-tri2.rb create mode 100644 doc/tri3.rb create mode 100644 doc/triangle.rb create mode 100644 emacs/.svn/README.txt create mode 100644 emacs/.svn/dir-prop-base create mode 100644 emacs/.svn/dir-props create mode 100644 emacs/.svn/empty-file create mode 100644 emacs/.svn/entries create mode 100644 emacs/.svn/format create mode 100644 emacs/.svn/prop-base/Makefile.am.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-annotate.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-breaks.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-cmd.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-core.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-dbg.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-error.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-fns.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-frames.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-gud.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-help.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-info.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-layouts.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-locring.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-output.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-regexp.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-secondary.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-shortkey.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-source.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-track.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-varbuf.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-vars.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug-watch.el.svn-base create mode 100644 emacs/.svn/prop-base/rdebug.el.svn-base create mode 100644 emacs/.svn/props/Makefile.am.svn-work create mode 100644 emacs/.svn/props/rdebug-annotate.el.svn-work create mode 100644 emacs/.svn/props/rdebug-breaks.el.svn-work create mode 100644 emacs/.svn/props/rdebug-cmd.el.svn-work create mode 100644 emacs/.svn/props/rdebug-core.el.svn-work create mode 100644 emacs/.svn/props/rdebug-dbg.el.svn-work create mode 100644 emacs/.svn/props/rdebug-error.el.svn-work create mode 100644 emacs/.svn/props/rdebug-fns.el.svn-work create mode 100644 emacs/.svn/props/rdebug-frames.el.svn-work create mode 100644 emacs/.svn/props/rdebug-gud.el.svn-work create mode 100644 emacs/.svn/props/rdebug-help.el.svn-work create mode 100644 emacs/.svn/props/rdebug-info.el.svn-work create mode 100644 emacs/.svn/props/rdebug-layouts.el.svn-work create mode 100644 emacs/.svn/props/rdebug-locring.el.svn-work create mode 100644 emacs/.svn/props/rdebug-output.el.svn-work create mode 100644 emacs/.svn/props/rdebug-regexp.el.svn-work create mode 100644 emacs/.svn/props/rdebug-secondary.el.svn-work create mode 100644 emacs/.svn/props/rdebug-shortkey.el.svn-work create mode 100644 emacs/.svn/props/rdebug-source.el.svn-work create mode 100644 emacs/.svn/props/rdebug-track.el.svn-work create mode 100644 emacs/.svn/props/rdebug-varbuf.el.svn-work create mode 100644 emacs/.svn/props/rdebug-vars.el.svn-work create mode 100644 emacs/.svn/props/rdebug-watch.el.svn-work create mode 100644 emacs/.svn/props/rdebug.el.svn-work create mode 100644 emacs/.svn/text-base/Makefile.am.svn-base create mode 100644 emacs/.svn/text-base/rdebug-annotate.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-breaks.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-cmd.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-core.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-dbg.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-error.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-fns.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-frames.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-gud.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-help.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-info.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-layouts.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-locring.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-output.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-regexp.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-secondary.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-shortkey.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-source.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-track.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-varbuf.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-vars.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug-watch.el.svn-base create mode 100644 emacs/.svn/text-base/rdebug.el.svn-base create mode 100644 emacs/Makefile.am create mode 100644 emacs/rdebug-annotate.el create mode 100644 emacs/rdebug-breaks.el create mode 100644 emacs/rdebug-cmd.el create mode 100644 emacs/rdebug-core.el create mode 100644 emacs/rdebug-dbg.el create mode 100644 emacs/rdebug-error.el create mode 100644 emacs/rdebug-fns.el create mode 100644 emacs/rdebug-frames.el create mode 100644 emacs/rdebug-gud.el create mode 100644 emacs/rdebug-help.el create mode 100644 emacs/rdebug-info.el create mode 100644 emacs/rdebug-layouts.el create mode 100644 emacs/rdebug-locring.el create mode 100644 emacs/rdebug-output.el create mode 100644 emacs/rdebug-regexp.el create mode 100644 emacs/rdebug-secondary.el create mode 100644 emacs/rdebug-shortkey.el create mode 100644 emacs/rdebug-source.el create mode 100644 emacs/rdebug-track.el create mode 100644 emacs/rdebug-varbuf.el create mode 100644 emacs/rdebug-vars.el create mode 100644 emacs/rdebug-watch.el create mode 100644 emacs/rdebug.el create mode 100644 emacs/test/.svn/README.txt create mode 100644 emacs/test/.svn/empty-file create mode 100644 emacs/test/.svn/entries create mode 100644 emacs/test/.svn/format create mode 100644 emacs/test/.svn/prop-base/elk-test.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-annotate.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-cmd.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-core.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-fns.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-frames.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-gud.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-indent.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-regexp.el.svn-base create mode 100644 emacs/test/.svn/prop-base/test-shortkey.el.svn-base create mode 100644 emacs/test/.svn/props/elk-test.el.svn-work create mode 100644 emacs/test/.svn/props/test-annotate.el.svn-work create mode 100644 emacs/test/.svn/props/test-cmd.el.svn-work create mode 100644 emacs/test/.svn/props/test-core.el.svn-work create mode 100644 emacs/test/.svn/props/test-fns.el.svn-work create mode 100644 emacs/test/.svn/props/test-frames.el.svn-work create mode 100644 emacs/test/.svn/props/test-gud.el.svn-work create mode 100644 emacs/test/.svn/props/test-indent.el.svn-work create mode 100644 emacs/test/.svn/props/test-regexp.el.svn-work create mode 100644 emacs/test/.svn/props/test-shortkey.el.svn-work create mode 100644 emacs/test/.svn/text-base/elk-test.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-annotate.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-cmd.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-core.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-fns.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-frames.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-gud.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-indent.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-regexp.el.svn-base create mode 100644 emacs/test/.svn/text-base/test-shortkey.el.svn-base create mode 100644 emacs/test/elk-test.el create mode 100644 emacs/test/test-annotate.el create mode 100644 emacs/test/test-cmd.el create mode 100644 emacs/test/test-core.el create mode 100644 emacs/test/test-fns.el create mode 100644 emacs/test/test-frames.el create mode 100644 emacs/test/test-gud.el create mode 100644 emacs/test/test-indent.el create mode 100644 emacs/test/test-regexp.el create mode 100644 emacs/test/test-shortkey.el create mode 100644 ext/.svn/README.txt create mode 100644 ext/.svn/dir-prop-base create mode 100644 ext/.svn/dir-props create mode 100644 ext/.svn/empty-file create mode 100644 ext/.svn/entries create mode 100644 ext/.svn/format create mode 100644 ext/.svn/prop-base/breakpoint.c.svn-base create mode 100644 ext/.svn/prop-base/extconf.rb.svn-base create mode 100644 ext/.svn/prop-base/ruby_debug.c.svn-base create mode 100644 ext/.svn/prop-base/ruby_debug.h.svn-base create mode 100644 ext/.svn/props/breakpoint.c.svn-work create mode 100644 ext/.svn/props/extconf.rb.svn-work create mode 100644 ext/.svn/props/ruby_debug.c.svn-work create mode 100644 ext/.svn/props/ruby_debug.h.svn-work create mode 100644 ext/.svn/text-base/breakpoint.c.svn-base create mode 100644 ext/.svn/text-base/extconf.rb.svn-base create mode 100644 ext/.svn/text-base/ruby_debug.c.svn-base create mode 100644 ext/.svn/text-base/ruby_debug.h.svn-base create mode 100644 ext/breakpoint.c create mode 100644 ext/extconf.rb create mode 100644 ext/ruby_debug.c create mode 100644 ext/ruby_debug.h create mode 100644 ext/win32/.cvsignore create mode 100644 ext/win32/.svn/README.txt create mode 100644 ext/win32/.svn/dir-prop-base create mode 100644 ext/win32/.svn/dir-props create mode 100644 ext/win32/.svn/empty-file create mode 100644 ext/win32/.svn/entries create mode 100644 ext/win32/.svn/format create mode 100644 ext/win32/.svn/prop-base/.cvsignore.svn-base create mode 100644 ext/win32/.svn/props/.cvsignore.svn-work create mode 100644 ext/win32/.svn/text-base/.cvsignore.svn-base create mode 100644 lib/.svn/README.txt create mode 100644 lib/.svn/empty-file create mode 100644 lib/.svn/entries create mode 100644 lib/.svn/format create mode 100644 lib/.svn/prop-base/ChangeLog.svn-base create mode 100644 lib/.svn/prop-base/ruby-debug-base.rb.svn-base create mode 100644 lib/.svn/props/ChangeLog.svn-work create mode 100644 lib/.svn/props/ruby-debug-base.rb.svn-work create mode 100644 lib/.svn/text-base/ChangeLog.svn-base create mode 100644 lib/.svn/text-base/ruby-debug-base.rb.svn-base create mode 100644 lib/ChangeLog create mode 100644 lib/ruby-debug-base.rb create mode 100755 rdbg.rb create mode 100755 runner.sh create mode 100644 svn2cl_usermap create mode 100644 test/.cvsignore create mode 100644 test/.svn/README.txt create mode 100644 test/.svn/dir-prop-base create mode 100644 test/.svn/dir-props create mode 100644 test/.svn/empty-file create mode 100644 test/.svn/entries create mode 100644 test/.svn/format create mode 100644 test/.svn/prop-base/.cvsignore.svn-base create mode 100644 test/.svn/prop-base/bp_loop_issue.rb.svn-base create mode 100644 test/.svn/prop-base/classes.rb.svn-base create mode 100644 test/.svn/prop-base/config.yaml.svn-base create mode 100644 test/.svn/prop-base/dollar-0.rb.svn-base create mode 100644 test/.svn/prop-base/gcd-dbg-nox.rb.svn-base create mode 100644 test/.svn/prop-base/gcd-dbg.rb.svn-base create mode 100644 test/.svn/prop-base/gcd.rb.svn-base create mode 100644 test/.svn/prop-base/helper.rb.svn-base create mode 100644 test/.svn/prop-base/info-var-bug.rb.svn-base create mode 100644 test/.svn/prop-base/info-var-bug2.rb.svn-base create mode 100644 test/.svn/prop-base/null.rb.svn-base create mode 100644 test/.svn/prop-base/output.rb.svn-base create mode 100644 test/.svn/prop-base/pm-base.rb.svn-base create mode 100644 test/.svn/prop-base/pm-bug.rb.svn-base create mode 100644 test/.svn/prop-base/pm.rb.svn-base create mode 100644 test/.svn/prop-base/raise.rb.svn-base create mode 100644 test/.svn/prop-base/rdebug-save.1.svn-base create mode 100644 test/.svn/prop-base/runall.svn-base create mode 100644 test/.svn/prop-base/tdebug.rb.svn-base create mode 100644 test/.svn/prop-base/test-annotate.rb.svn-base create mode 100644 test/.svn/prop-base/test-break-bad.rb.svn-base create mode 100644 test/.svn/prop-base/test-breakpoints.rb.svn-base create mode 100644 test/.svn/prop-base/test-catch.rb.svn-base create mode 100644 test/.svn/prop-base/test-condition.rb.svn-base create mode 100644 test/.svn/prop-base/test-ctrl.rb.svn-base create mode 100644 test/.svn/prop-base/test-display.rb.svn-base create mode 100644 test/.svn/prop-base/test-dollar-0.rb.svn-base create mode 100644 test/.svn/prop-base/test-edit.rb.svn-base create mode 100644 test/.svn/prop-base/test-emacs-basic.rb.svn-base create mode 100644 test/.svn/prop-base/test-enable.rb.svn-base create mode 100644 test/.svn/prop-base/test-finish.rb.svn-base create mode 100644 test/.svn/prop-base/test-frame.rb.svn-base create mode 100644 test/.svn/prop-base/test-help.rb.svn-base create mode 100644 test/.svn/prop-base/test-hist.rb.svn-base create mode 100644 test/.svn/prop-base/test-info-thread.rb.svn-base create mode 100644 test/.svn/prop-base/test-info-var.rb.svn-base create mode 100644 test/.svn/prop-base/test-info.rb.svn-base create mode 100644 test/.svn/prop-base/test-init.rb.svn-base create mode 100644 test/.svn/prop-base/test-list.rb.svn-base create mode 100644 test/.svn/prop-base/test-method.rb.svn-base create mode 100644 test/.svn/prop-base/test-output.rb.svn-base create mode 100644 test/.svn/prop-base/test-pm.rb.svn-base create mode 100644 test/.svn/prop-base/test-quit.rb.svn-base create mode 100644 test/.svn/prop-base/test-raise.rb.svn-base create mode 100644 test/.svn/prop-base/test-save.rb.svn-base create mode 100644 test/.svn/prop-base/test-setshow.rb.svn-base create mode 100644 test/.svn/prop-base/test-source.rb.svn-base create mode 100644 test/.svn/prop-base/test-stepping.rb.svn-base create mode 100644 test/.svn/prop-base/test-trace.rb.svn-base create mode 100644 test/.svn/prop-base/thread1.rb.svn-base create mode 100644 test/.svn/prop-base/trunc-call.rb.svn-base create mode 100644 test/.svn/props/.cvsignore.svn-work create mode 100644 test/.svn/props/bp_loop_issue.rb.svn-work create mode 100644 test/.svn/props/classes.rb.svn-work create mode 100644 test/.svn/props/config.yaml.svn-work create mode 100644 test/.svn/props/dollar-0.rb.svn-work create mode 100644 test/.svn/props/gcd-dbg-nox.rb.svn-work create mode 100644 test/.svn/props/gcd-dbg.rb.svn-work create mode 100644 test/.svn/props/gcd.rb.svn-work create mode 100644 test/.svn/props/helper.rb.svn-work create mode 100644 test/.svn/props/info-var-bug.rb.svn-work create mode 100644 test/.svn/props/info-var-bug2.rb.svn-work create mode 100644 test/.svn/props/null.rb.svn-work create mode 100644 test/.svn/props/output.rb.svn-work create mode 100644 test/.svn/props/pm-base.rb.svn-work create mode 100644 test/.svn/props/pm-bug.rb.svn-work create mode 100644 test/.svn/props/pm.rb.svn-work create mode 100644 test/.svn/props/raise.rb.svn-work create mode 100644 test/.svn/props/rdebug-save.1.svn-work create mode 100644 test/.svn/props/runall.svn-work create mode 100644 test/.svn/props/tdebug.rb.svn-work create mode 100644 test/.svn/props/test-annotate.rb.svn-work create mode 100644 test/.svn/props/test-break-bad.rb.svn-work create mode 100644 test/.svn/props/test-breakpoints.rb.svn-work create mode 100644 test/.svn/props/test-catch.rb.svn-work create mode 100644 test/.svn/props/test-condition.rb.svn-work create mode 100644 test/.svn/props/test-ctrl.rb.svn-work create mode 100644 test/.svn/props/test-display.rb.svn-work create mode 100644 test/.svn/props/test-dollar-0.rb.svn-work create mode 100644 test/.svn/props/test-edit.rb.svn-work create mode 100644 test/.svn/props/test-emacs-basic.rb.svn-work create mode 100644 test/.svn/props/test-enable.rb.svn-work create mode 100644 test/.svn/props/test-finish.rb.svn-work create mode 100644 test/.svn/props/test-frame.rb.svn-work create mode 100644 test/.svn/props/test-help.rb.svn-work create mode 100644 test/.svn/props/test-hist.rb.svn-work create mode 100644 test/.svn/props/test-info-thread.rb.svn-work create mode 100644 test/.svn/props/test-info-var.rb.svn-work create mode 100644 test/.svn/props/test-info.rb.svn-work create mode 100644 test/.svn/props/test-init.rb.svn-work create mode 100644 test/.svn/props/test-list.rb.svn-work create mode 100644 test/.svn/props/test-method.rb.svn-work create mode 100644 test/.svn/props/test-output.rb.svn-work create mode 100644 test/.svn/props/test-pm.rb.svn-work create mode 100644 test/.svn/props/test-quit.rb.svn-work create mode 100644 test/.svn/props/test-raise.rb.svn-work create mode 100644 test/.svn/props/test-save.rb.svn-work create mode 100644 test/.svn/props/test-setshow.rb.svn-work create mode 100644 test/.svn/props/test-source.rb.svn-work create mode 100644 test/.svn/props/test-stepping.rb.svn-work create mode 100644 test/.svn/props/test-trace.rb.svn-work create mode 100644 test/.svn/props/thread1.rb.svn-work create mode 100644 test/.svn/props/trunc-call.rb.svn-work create mode 100644 test/.svn/text-base/.cvsignore.svn-base create mode 100644 test/.svn/text-base/bp_loop_issue.rb.svn-base create mode 100644 test/.svn/text-base/classes.rb.svn-base create mode 100644 test/.svn/text-base/config.yaml.svn-base create mode 100644 test/.svn/text-base/dollar-0.rb.svn-base create mode 100644 test/.svn/text-base/gcd-dbg-nox.rb.svn-base create mode 100644 test/.svn/text-base/gcd-dbg.rb.svn-base create mode 100644 test/.svn/text-base/gcd.rb.svn-base create mode 100644 test/.svn/text-base/helper.rb.svn-base create mode 100644 test/.svn/text-base/info-var-bug.rb.svn-base create mode 100644 test/.svn/text-base/info-var-bug2.rb.svn-base create mode 100644 test/.svn/text-base/null.rb.svn-base create mode 100644 test/.svn/text-base/output.rb.svn-base create mode 100644 test/.svn/text-base/pm-base.rb.svn-base create mode 100644 test/.svn/text-base/pm-bug.rb.svn-base create mode 100644 test/.svn/text-base/pm.rb.svn-base create mode 100644 test/.svn/text-base/raise.rb.svn-base create mode 100644 test/.svn/text-base/rdebug-save.1.svn-base create mode 100644 test/.svn/text-base/runall.svn-base create mode 100644 test/.svn/text-base/tdebug.rb.svn-base create mode 100644 test/.svn/text-base/test-annotate.rb.svn-base create mode 100644 test/.svn/text-base/test-break-bad.rb.svn-base create mode 100644 test/.svn/text-base/test-breakpoints.rb.svn-base create mode 100644 test/.svn/text-base/test-catch.rb.svn-base create mode 100644 test/.svn/text-base/test-condition.rb.svn-base create mode 100644 test/.svn/text-base/test-ctrl.rb.svn-base create mode 100644 test/.svn/text-base/test-display.rb.svn-base create mode 100644 test/.svn/text-base/test-dollar-0.rb.svn-base create mode 100644 test/.svn/text-base/test-edit.rb.svn-base create mode 100644 test/.svn/text-base/test-emacs-basic.rb.svn-base create mode 100644 test/.svn/text-base/test-enable.rb.svn-base create mode 100644 test/.svn/text-base/test-finish.rb.svn-base create mode 100644 test/.svn/text-base/test-frame.rb.svn-base create mode 100644 test/.svn/text-base/test-help.rb.svn-base create mode 100644 test/.svn/text-base/test-hist.rb.svn-base create mode 100644 test/.svn/text-base/test-info-thread.rb.svn-base create mode 100644 test/.svn/text-base/test-info-var.rb.svn-base create mode 100644 test/.svn/text-base/test-info.rb.svn-base create mode 100644 test/.svn/text-base/test-init.rb.svn-base create mode 100644 test/.svn/text-base/test-list.rb.svn-base create mode 100644 test/.svn/text-base/test-method.rb.svn-base create mode 100644 test/.svn/text-base/test-output.rb.svn-base create mode 100644 test/.svn/text-base/test-pm.rb.svn-base create mode 100644 test/.svn/text-base/test-quit.rb.svn-base create mode 100644 test/.svn/text-base/test-raise.rb.svn-base create mode 100644 test/.svn/text-base/test-save.rb.svn-base create mode 100644 test/.svn/text-base/test-setshow.rb.svn-base create mode 100644 test/.svn/text-base/test-source.rb.svn-base create mode 100644 test/.svn/text-base/test-stepping.rb.svn-base create mode 100644 test/.svn/text-base/test-trace.rb.svn-base create mode 100644 test/.svn/text-base/thread1.rb.svn-base create mode 100644 test/.svn/text-base/trunc-call.rb.svn-base create mode 100644 test/base/.svn/README.txt create mode 100644 test/base/.svn/empty-file create mode 100644 test/base/.svn/entries create mode 100644 test/base/.svn/format create mode 100644 test/base/.svn/prop-base/base.rb.svn-base create mode 100644 test/base/.svn/prop-base/binding.rb.svn-base create mode 100644 test/base/.svn/prop-base/catchpoint.rb.svn-base create mode 100644 test/base/.svn/prop-base/load.rb.svn-base create mode 100644 test/base/.svn/props/base.rb.svn-work create mode 100644 test/base/.svn/props/binding.rb.svn-work create mode 100644 test/base/.svn/props/catchpoint.rb.svn-work create mode 100644 test/base/.svn/props/load.rb.svn-work create mode 100644 test/base/.svn/text-base/base.rb.svn-base create mode 100644 test/base/.svn/text-base/binding.rb.svn-base create mode 100644 test/base/.svn/text-base/catchpoint.rb.svn-base create mode 100644 test/base/.svn/text-base/load.rb.svn-base create mode 100755 test/base/base.rb create mode 100755 test/base/binding.rb create mode 100755 test/base/catchpoint.rb create mode 100644 test/base/load.rb create mode 100644 test/bp_loop_issue.rb create mode 100644 test/classes.rb create mode 100644 test/cli/.svn/README.txt create mode 100644 test/cli/.svn/empty-file create mode 100644 test/cli/.svn/entries create mode 100644 test/cli/.svn/format create mode 100644 test/cli/commands/.svn/README.txt create mode 100644 test/cli/commands/.svn/empty-file create mode 100644 test/cli/commands/.svn/entries create mode 100644 test/cli/commands/.svn/format create mode 100644 test/cli/commands/.svn/prop-base/catchpoint_test.rb.svn-base create mode 100644 test/cli/commands/.svn/props/catchpoint_test.rb.svn-work create mode 100644 test/cli/commands/.svn/text-base/catchpoint_test.rb.svn-base create mode 100644 test/cli/commands/catchpoint_test.rb create mode 100644 test/cli/commands/unit/.svn/README.txt create mode 100644 test/cli/commands/unit/.svn/empty-file create mode 100644 test/cli/commands/unit/.svn/entries create mode 100644 test/cli/commands/unit/.svn/format create mode 100644 test/cli/commands/unit/.svn/prop-base/regexp.rb.svn-base create mode 100644 test/cli/commands/unit/.svn/props/regexp.rb.svn-work create mode 100644 test/cli/commands/unit/.svn/text-base/regexp.rb.svn-base create mode 100644 test/cli/commands/unit/regexp.rb create mode 100644 test/config.yaml create mode 100644 test/data/.svn/README.txt create mode 100644 test/data/.svn/empty-file create mode 100644 test/data/.svn/entries create mode 100644 test/data/.svn/format create mode 100644 test/data/.svn/prop-base/annotate.cmd.svn-base create mode 100644 test/data/.svn/prop-base/annotate.right.svn-base create mode 100644 test/data/.svn/prop-base/break_bad.cmd.svn-base create mode 100644 test/data/.svn/prop-base/break_bad.right.svn-base create mode 100644 test/data/.svn/prop-base/break_loop_bug.cmd.svn-base create mode 100644 test/data/.svn/prop-base/break_loop_bug.right.svn-base create mode 100644 test/data/.svn/prop-base/breakpoints.cmd.svn-base create mode 100644 test/data/.svn/prop-base/breakpoints.right.svn-base create mode 100644 test/data/.svn/prop-base/catch.cmd.svn-base create mode 100644 test/data/.svn/prop-base/catch.right.svn-base create mode 100644 test/data/.svn/prop-base/condition.cmd.svn-base create mode 100644 test/data/.svn/prop-base/condition.right.svn-base create mode 100644 test/data/.svn/prop-base/ctrl.cmd.svn-base create mode 100644 test/data/.svn/prop-base/ctrl.right.svn-base create mode 100644 test/data/.svn/prop-base/display.cmd.svn-base create mode 100644 test/data/.svn/prop-base/display.right.svn-base create mode 100644 test/data/.svn/prop-base/dollar-0.right.svn-base create mode 100644 test/data/.svn/prop-base/dollar-0a.right.svn-base create mode 100644 test/data/.svn/prop-base/dollar-0b.right.svn-base create mode 100644 test/data/.svn/prop-base/edit.cmd.svn-base create mode 100644 test/data/.svn/prop-base/edit.right.svn-base create mode 100644 test/data/.svn/prop-base/emacs_basic.cmd.svn-base create mode 100644 test/data/.svn/prop-base/emacs_basic.right.svn-base create mode 100644 test/data/.svn/prop-base/enable.cmd.svn-base create mode 100644 test/data/.svn/prop-base/enable.right.svn-base create mode 100644 test/data/.svn/prop-base/finish.cmd.svn-base create mode 100644 test/data/.svn/prop-base/finish.right.svn-base create mode 100644 test/data/.svn/prop-base/frame.cmd.svn-base create mode 100644 test/data/.svn/prop-base/frame.right.svn-base create mode 100644 test/data/.svn/prop-base/help.cmd.svn-base create mode 100644 test/data/.svn/prop-base/help.right.svn-base create mode 100644 test/data/.svn/prop-base/history.right.svn-base create mode 100644 test/data/.svn/prop-base/info-thread.cmd.svn-base create mode 100644 test/data/.svn/prop-base/info-thread.right.svn-base create mode 100644 test/data/.svn/prop-base/info-var-bug2.cmd.svn-base create mode 100644 test/data/.svn/prop-base/info-var-bug2.right.svn-base create mode 100644 test/data/.svn/prop-base/info-var.cmd.svn-base create mode 100644 test/data/.svn/prop-base/info-var.right.svn-base create mode 100644 test/data/.svn/prop-base/info.cmd.svn-base create mode 100644 test/data/.svn/prop-base/info.right.svn-base create mode 100644 test/data/.svn/prop-base/linetrace.cmd.svn-base create mode 100644 test/data/.svn/prop-base/linetrace.right.svn-base create mode 100644 test/data/.svn/prop-base/linetracep.cmd.svn-base create mode 100644 test/data/.svn/prop-base/linetracep.right.svn-base create mode 100644 test/data/.svn/prop-base/list.cmd.svn-base create mode 100644 test/data/.svn/prop-base/list.right.svn-base create mode 100644 test/data/.svn/prop-base/method.cmd.svn-base create mode 100644 test/data/.svn/prop-base/method.right.svn-base create mode 100644 test/data/.svn/prop-base/methodsig.cmd.svn-base create mode 100644 test/data/.svn/prop-base/methodsig.right.svn-base create mode 100644 test/data/.svn/prop-base/noquit.right.svn-base create mode 100644 test/data/.svn/prop-base/output.cmd.svn-base create mode 100644 test/data/.svn/prop-base/output.right.svn-base create mode 100644 test/data/.svn/prop-base/pm-bug.cmd.svn-base create mode 100644 test/data/.svn/prop-base/pm-bug.right.svn-base create mode 100644 test/data/.svn/prop-base/post-mortem-next.cmd.svn-base create mode 100644 test/data/.svn/prop-base/post-mortem-next.right.svn-base create mode 100644 test/data/.svn/prop-base/post-mortem-osx.right.svn-base create mode 100644 test/data/.svn/prop-base/post-mortem.cmd.svn-base create mode 100644 test/data/.svn/prop-base/post-mortem.right.svn-base create mode 100644 test/data/.svn/prop-base/quit.cmd.svn-base create mode 100644 test/data/.svn/prop-base/quit.right.svn-base create mode 100644 test/data/.svn/prop-base/raise.cmd.svn-base create mode 100644 test/data/.svn/prop-base/raise.right.svn-base create mode 100644 test/data/.svn/prop-base/save.cmd.svn-base create mode 100644 test/data/.svn/prop-base/save.right.svn-base create mode 100644 test/data/.svn/prop-base/setshow.cmd.svn-base create mode 100644 test/data/.svn/prop-base/setshow.right.svn-base create mode 100644 test/data/.svn/prop-base/source.cmd.svn-base create mode 100644 test/data/.svn/prop-base/source.right.svn-base create mode 100644 test/data/.svn/prop-base/stepping.cmd.svn-base create mode 100644 test/data/.svn/prop-base/stepping.right.svn-base create mode 100644 test/data/.svn/prop-base/test-init-cygwin.right.svn-base create mode 100644 test/data/.svn/prop-base/test-init-osx.right.svn-base create mode 100644 test/data/.svn/prop-base/test-init.right.svn-base create mode 100644 test/data/.svn/prop-base/trace.right.svn-base create mode 100644 test/data/.svn/props/annotate.cmd.svn-work create mode 100644 test/data/.svn/props/annotate.right.svn-work create mode 100644 test/data/.svn/props/break_bad.cmd.svn-work create mode 100644 test/data/.svn/props/break_bad.right.svn-work create mode 100644 test/data/.svn/props/break_loop_bug.cmd.svn-work create mode 100644 test/data/.svn/props/break_loop_bug.right.svn-work create mode 100644 test/data/.svn/props/breakpoints.cmd.svn-work create mode 100644 test/data/.svn/props/breakpoints.right.svn-work create mode 100644 test/data/.svn/props/catch.cmd.svn-work create mode 100644 test/data/.svn/props/catch.right.svn-work create mode 100644 test/data/.svn/props/condition.cmd.svn-work create mode 100644 test/data/.svn/props/condition.right.svn-work create mode 100644 test/data/.svn/props/ctrl.cmd.svn-work create mode 100644 test/data/.svn/props/ctrl.right.svn-work create mode 100644 test/data/.svn/props/display.cmd.svn-work create mode 100644 test/data/.svn/props/display.right.svn-work create mode 100644 test/data/.svn/props/dollar-0.right.svn-work create mode 100644 test/data/.svn/props/dollar-0a.right.svn-work create mode 100644 test/data/.svn/props/dollar-0b.right.svn-work create mode 100644 test/data/.svn/props/edit.cmd.svn-work create mode 100644 test/data/.svn/props/edit.right.svn-work create mode 100644 test/data/.svn/props/emacs_basic.cmd.svn-work create mode 100644 test/data/.svn/props/emacs_basic.right.svn-work create mode 100644 test/data/.svn/props/enable.cmd.svn-work create mode 100644 test/data/.svn/props/enable.right.svn-work create mode 100644 test/data/.svn/props/finish.cmd.svn-work create mode 100644 test/data/.svn/props/finish.right.svn-work create mode 100644 test/data/.svn/props/frame.cmd.svn-work create mode 100644 test/data/.svn/props/frame.right.svn-work create mode 100644 test/data/.svn/props/help.cmd.svn-work create mode 100644 test/data/.svn/props/help.right.svn-work create mode 100644 test/data/.svn/props/history.right.svn-work create mode 100644 test/data/.svn/props/info-thread.cmd.svn-work create mode 100644 test/data/.svn/props/info-thread.right.svn-work create mode 100644 test/data/.svn/props/info-var-bug2.cmd.svn-work create mode 100644 test/data/.svn/props/info-var-bug2.right.svn-work create mode 100644 test/data/.svn/props/info-var.cmd.svn-work create mode 100644 test/data/.svn/props/info-var.right.svn-work create mode 100644 test/data/.svn/props/info.cmd.svn-work create mode 100644 test/data/.svn/props/info.right.svn-work create mode 100644 test/data/.svn/props/linetrace.cmd.svn-work create mode 100644 test/data/.svn/props/linetrace.right.svn-work create mode 100644 test/data/.svn/props/linetracep.cmd.svn-work create mode 100644 test/data/.svn/props/linetracep.right.svn-work create mode 100644 test/data/.svn/props/list.cmd.svn-work create mode 100644 test/data/.svn/props/list.right.svn-work create mode 100644 test/data/.svn/props/method.cmd.svn-work create mode 100644 test/data/.svn/props/method.right.svn-work create mode 100644 test/data/.svn/props/methodsig.cmd.svn-work create mode 100644 test/data/.svn/props/methodsig.right.svn-work create mode 100644 test/data/.svn/props/noquit.right.svn-work create mode 100644 test/data/.svn/props/output.cmd.svn-work create mode 100644 test/data/.svn/props/output.right.svn-work create mode 100644 test/data/.svn/props/pm-bug.cmd.svn-work create mode 100644 test/data/.svn/props/pm-bug.right.svn-work create mode 100644 test/data/.svn/props/post-mortem-next.cmd.svn-work create mode 100644 test/data/.svn/props/post-mortem-next.right.svn-work create mode 100644 test/data/.svn/props/post-mortem-osx.right.svn-work create mode 100644 test/data/.svn/props/post-mortem.cmd.svn-work create mode 100644 test/data/.svn/props/post-mortem.right.svn-work create mode 100644 test/data/.svn/props/quit.cmd.svn-work create mode 100644 test/data/.svn/props/quit.right.svn-work create mode 100644 test/data/.svn/props/raise.cmd.svn-work create mode 100644 test/data/.svn/props/raise.right.svn-work create mode 100644 test/data/.svn/props/save.cmd.svn-work create mode 100644 test/data/.svn/props/save.right.svn-work create mode 100644 test/data/.svn/props/setshow.cmd.svn-work create mode 100644 test/data/.svn/props/setshow.right.svn-work create mode 100644 test/data/.svn/props/source.cmd.svn-work create mode 100644 test/data/.svn/props/source.right.svn-work create mode 100644 test/data/.svn/props/stepping.cmd.svn-work create mode 100644 test/data/.svn/props/stepping.right.svn-work create mode 100644 test/data/.svn/props/test-init-cygwin.right.svn-work create mode 100644 test/data/.svn/props/test-init-osx.right.svn-work create mode 100644 test/data/.svn/props/test-init.right.svn-work create mode 100644 test/data/.svn/props/trace.right.svn-work create mode 100644 test/data/.svn/text-base/annotate.cmd.svn-base create mode 100644 test/data/.svn/text-base/annotate.right.svn-base create mode 100644 test/data/.svn/text-base/break_bad.cmd.svn-base create mode 100644 test/data/.svn/text-base/break_bad.right.svn-base create mode 100644 test/data/.svn/text-base/break_loop_bug.cmd.svn-base create mode 100644 test/data/.svn/text-base/break_loop_bug.right.svn-base create mode 100644 test/data/.svn/text-base/breakpoints.cmd.svn-base create mode 100644 test/data/.svn/text-base/breakpoints.right.svn-base create mode 100644 test/data/.svn/text-base/catch.cmd.svn-base create mode 100644 test/data/.svn/text-base/catch.right.svn-base create mode 100644 test/data/.svn/text-base/condition.cmd.svn-base create mode 100644 test/data/.svn/text-base/condition.right.svn-base create mode 100644 test/data/.svn/text-base/ctrl.cmd.svn-base create mode 100644 test/data/.svn/text-base/ctrl.right.svn-base create mode 100644 test/data/.svn/text-base/display.cmd.svn-base create mode 100644 test/data/.svn/text-base/display.right.svn-base create mode 100644 test/data/.svn/text-base/dollar-0.right.svn-base create mode 100644 test/data/.svn/text-base/dollar-0a.right.svn-base create mode 100644 test/data/.svn/text-base/dollar-0b.right.svn-base create mode 100644 test/data/.svn/text-base/edit.cmd.svn-base create mode 100644 test/data/.svn/text-base/edit.right.svn-base create mode 100644 test/data/.svn/text-base/emacs_basic.cmd.svn-base create mode 100644 test/data/.svn/text-base/emacs_basic.right.svn-base create mode 100644 test/data/.svn/text-base/enable.cmd.svn-base create mode 100644 test/data/.svn/text-base/enable.right.svn-base create mode 100644 test/data/.svn/text-base/finish.cmd.svn-base create mode 100644 test/data/.svn/text-base/finish.right.svn-base create mode 100644 test/data/.svn/text-base/frame.cmd.svn-base create mode 100644 test/data/.svn/text-base/frame.right.svn-base create mode 100644 test/data/.svn/text-base/help.cmd.svn-base create mode 100644 test/data/.svn/text-base/help.right.svn-base create mode 100644 test/data/.svn/text-base/history.right.svn-base create mode 100644 test/data/.svn/text-base/info-thread.cmd.svn-base create mode 100644 test/data/.svn/text-base/info-thread.right.svn-base create mode 100644 test/data/.svn/text-base/info-var-bug2.cmd.svn-base create mode 100644 test/data/.svn/text-base/info-var-bug2.right.svn-base create mode 100644 test/data/.svn/text-base/info-var.cmd.svn-base create mode 100644 test/data/.svn/text-base/info-var.right.svn-base create mode 100644 test/data/.svn/text-base/info.cmd.svn-base create mode 100644 test/data/.svn/text-base/info.right.svn-base create mode 100644 test/data/.svn/text-base/linetrace.cmd.svn-base create mode 100644 test/data/.svn/text-base/linetrace.right.svn-base create mode 100644 test/data/.svn/text-base/linetracep.cmd.svn-base create mode 100644 test/data/.svn/text-base/linetracep.right.svn-base create mode 100644 test/data/.svn/text-base/list.cmd.svn-base create mode 100644 test/data/.svn/text-base/list.right.svn-base create mode 100644 test/data/.svn/text-base/method.cmd.svn-base create mode 100644 test/data/.svn/text-base/method.right.svn-base create mode 100644 test/data/.svn/text-base/methodsig.cmd.svn-base create mode 100644 test/data/.svn/text-base/methodsig.right.svn-base create mode 100644 test/data/.svn/text-base/noquit.right.svn-base create mode 100644 test/data/.svn/text-base/output.cmd.svn-base create mode 100644 test/data/.svn/text-base/output.right.svn-base create mode 100644 test/data/.svn/text-base/pm-bug.cmd.svn-base create mode 100644 test/data/.svn/text-base/pm-bug.right.svn-base create mode 100644 test/data/.svn/text-base/post-mortem-next.cmd.svn-base create mode 100644 test/data/.svn/text-base/post-mortem-next.right.svn-base create mode 100644 test/data/.svn/text-base/post-mortem-osx.right.svn-base create mode 100644 test/data/.svn/text-base/post-mortem.cmd.svn-base create mode 100644 test/data/.svn/text-base/post-mortem.right.svn-base create mode 100644 test/data/.svn/text-base/quit.cmd.svn-base create mode 100644 test/data/.svn/text-base/quit.right.svn-base create mode 100644 test/data/.svn/text-base/raise.cmd.svn-base create mode 100644 test/data/.svn/text-base/raise.right.svn-base create mode 100644 test/data/.svn/text-base/save.cmd.svn-base create mode 100644 test/data/.svn/text-base/save.right.svn-base create mode 100644 test/data/.svn/text-base/setshow.cmd.svn-base create mode 100644 test/data/.svn/text-base/setshow.right.svn-base create mode 100644 test/data/.svn/text-base/source.cmd.svn-base create mode 100644 test/data/.svn/text-base/source.right.svn-base create mode 100644 test/data/.svn/text-base/stepping.cmd.svn-base create mode 100644 test/data/.svn/text-base/stepping.right.svn-base create mode 100644 test/data/.svn/text-base/test-init-cygwin.right.svn-base create mode 100644 test/data/.svn/text-base/test-init-osx.right.svn-base create mode 100644 test/data/.svn/text-base/test-init.right.svn-base create mode 100644 test/data/.svn/text-base/trace.right.svn-base create mode 100644 test/data/annotate.cmd create mode 100644 test/data/annotate.right create mode 100644 test/data/break_bad.cmd create mode 100644 test/data/break_bad.right create mode 100644 test/data/break_loop_bug.cmd create mode 100644 test/data/break_loop_bug.right create mode 100644 test/data/breakpoints.cmd create mode 100644 test/data/breakpoints.right create mode 100644 test/data/catch.cmd create mode 100644 test/data/catch.right create mode 100644 test/data/condition.cmd create mode 100644 test/data/condition.right create mode 100644 test/data/ctrl.cmd create mode 100644 test/data/ctrl.right create mode 100644 test/data/display.cmd create mode 100644 test/data/display.right create mode 100644 test/data/dollar-0.right create mode 100644 test/data/dollar-0a.right create mode 100644 test/data/dollar-0b.right create mode 100644 test/data/edit.cmd create mode 100644 test/data/edit.right create mode 100644 test/data/emacs_basic.cmd create mode 100644 test/data/emacs_basic.right create mode 100644 test/data/enable.cmd create mode 100644 test/data/enable.right create mode 100644 test/data/finish.cmd create mode 100644 test/data/finish.right create mode 100644 test/data/frame.cmd create mode 100644 test/data/frame.right create mode 100644 test/data/help.cmd create mode 100644 test/data/help.right create mode 100644 test/data/history.right create mode 100644 test/data/info-thread.cmd create mode 100644 test/data/info-thread.right create mode 100644 test/data/info-var-bug2.cmd create mode 100644 test/data/info-var-bug2.right create mode 100644 test/data/info-var.cmd create mode 100644 test/data/info-var.right create mode 100644 test/data/info.cmd create mode 100644 test/data/info.right create mode 100644 test/data/linetrace.cmd create mode 100644 test/data/linetrace.right create mode 100644 test/data/linetracep.cmd create mode 100644 test/data/linetracep.right create mode 100644 test/data/list.cmd create mode 100644 test/data/list.right create mode 100644 test/data/method.cmd create mode 100644 test/data/method.right create mode 100644 test/data/methodsig.cmd create mode 100644 test/data/methodsig.right create mode 100644 test/data/noquit.right create mode 100644 test/data/output.cmd create mode 100644 test/data/output.right create mode 100644 test/data/pm-bug.cmd create mode 100644 test/data/pm-bug.right create mode 100644 test/data/post-mortem-next.cmd create mode 100644 test/data/post-mortem-next.right create mode 100644 test/data/post-mortem-osx.right create mode 100644 test/data/post-mortem.cmd create mode 100644 test/data/post-mortem.right create mode 100644 test/data/quit.cmd create mode 100644 test/data/quit.right create mode 100644 test/data/raise.cmd create mode 100644 test/data/raise.right create mode 100644 test/data/save.cmd create mode 100644 test/data/save.right create mode 100644 test/data/setshow.cmd create mode 100644 test/data/setshow.right create mode 100644 test/data/source.cmd create mode 100644 test/data/source.right create mode 100644 test/data/stepping.cmd create mode 100644 test/data/stepping.right create mode 100644 test/data/test-init-cygwin.right create mode 100644 test/data/test-init-osx.right create mode 100644 test/data/test-init.right create mode 100644 test/data/trace.right create mode 100755 test/dollar-0.rb create mode 100644 test/gcd-dbg-nox.rb create mode 100755 test/gcd-dbg.rb create mode 100644 test/gcd.rb create mode 100644 test/helper.rb create mode 100644 test/info-var-bug.rb create mode 100644 test/info-var-bug2.rb create mode 100644 test/null.rb create mode 100644 test/output.rb create mode 100755 test/pm-base.rb create mode 100644 test/pm-bug.rb create mode 100755 test/pm.rb create mode 100755 test/raise.rb create mode 100644 test/rdebug-save.1 create mode 100755 test/runall create mode 100755 test/tdebug.rb create mode 100755 test/test-annotate.rb create mode 100755 test/test-break-bad.rb create mode 100755 test/test-breakpoints.rb create mode 100755 test/test-catch.rb create mode 100755 test/test-condition.rb create mode 100755 test/test-ctrl.rb create mode 100755 test/test-display.rb create mode 100755 test/test-dollar-0.rb create mode 100755 test/test-edit.rb create mode 100755 test/test-emacs-basic.rb create mode 100755 test/test-enable.rb create mode 100755 test/test-finish.rb create mode 100755 test/test-frame.rb create mode 100755 test/test-help.rb create mode 100755 test/test-hist.rb create mode 100755 test/test-info-thread.rb create mode 100755 test/test-info-var.rb create mode 100755 test/test-info.rb create mode 100755 test/test-init.rb create mode 100755 test/test-list.rb create mode 100755 test/test-method.rb create mode 100755 test/test-output.rb create mode 100755 test/test-pm.rb create mode 100755 test/test-quit.rb create mode 100755 test/test-raise.rb create mode 100755 test/test-save.rb create mode 100755 test/test-setshow.rb create mode 100755 test/test-source.rb create mode 100755 test/test-stepping.rb create mode 100755 test/test-trace.rb create mode 100644 test/thread1.rb create mode 100644 test/trunc-call.rb diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..ab5f9f7 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +Author and maintainer: +Kent Sibilev + +Contributers: +Markus Barchfeld +R. Bernstein +Anders Lindgren diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..4c9d8b2 --- /dev/null +++ b/CHANGES @@ -0,0 +1,334 @@ +0.10.3 +11/17/08 + + - a backtrace now warns when it thinks the callstack is truncated which it + gets by comparing with caller() + - fix setting $0. + - fix bug in showing variables in post-mortem + - Document how Debugger.start with a block is intended to be used. + - Move Kernel#debugger from ruby-debug-base into ruby-debug + - Get regression tests working again + - Warn and add a "confirmation" when setting a breakpoint on a + file that is not loaded. + +0.10.2 + - debugger(steps=0) breaks inside of debugger rather than wait for a line event. + - trace var varname (stop|nostop) added which issues trace_var. + - start method is now properly defined in Debugger module + - fixed 'finish' command + - rdebug script now works with Ruby 1.8.7 + +0.10.1 +4/10/08 - in honor of the 30th Birthday of Kate Schwarz + +- bin/rdebug + + * "rdebug --post-mortem" now really catches uncaught exceptions and + brings you to post-mortem handling. "info program" shows the exception. + + * rdebug now searches using ENV['PATH'] for a Ruby program to debug + if the program name is not found and doesn't have any path + characters in it. + + * Use ~/.rdboptrc (rdbopt.ini on MS Windows) to change default options. + + * --emacs is now --emacs-basic while --emacs 3 now implies emacs-basic + ---annotate=3 --post-mortem --no-control --no-start --no-quit + +- rdebug (CLI) + + * "info" command additions and changes: + o fix bug in "info variables" when string had embedded %s' + o "info program" now shows uncaught exception information + o "info files" show what Ruby files are loaded + o "info file " specific file information of (e.g. time, # of lines, SHA1) + o "info catch" - Exceptions that can be caught in the current stack frame. + o "info "variables" shows "self" and class variables + o "info threads verbose" shows stack trace of all threads + o "info thread verbose" shows stack trace of thread . + + * "frame" command now accepts an optional thread number argument + + * Long information added to commands with subcommands: show, set, + info, enable, and disable. For example "help info " will give + more detailed information about the "info " command. + + * columnize now pulled in from a separate package. + + * add "var cl[ass]" command. Note "var const" can no longer be + abbreviated "var c"; use "var co" (or const or constant). + + * add "condition" command. Allow removal of condition. + + * $0 == __FILE__ when running rdebug should work -- most of the + time. See comments in code for a better solution. + + * rdebug command history can be displayed with "show commands". Fix a bug + in history saving. + + * INCOMPATIBLE CHANGE: "finish" works like gdb - stop just before the most + recent method finishes. Will now accept a number which stops that many + frames completed. (Note that return line numbers will be funny, the + first line of the method until Ruby 1.8.7.) + + * fix bug in 'list' command when wrapping off the end. + +- Emacs interaction drastically reworked, expanded, and improved. + +- rdebug base + * allow catching multiple exceptions. + INCOMPATIBLE CHANGE: variable "Debugger.catchpoint", a String, was turned + into "Debugger.catchpoints", a Hash. Method "Debugger.catchpoint=" no + longer exists. Debugger.set_catchpoint was turned into + Debugger.add_catchpoint + + * Add Debugger.last_exception which is set in post-mortem. + + * remove Debugger.stop() when an exception is raised that would terminate the + debugged program. This may allow catchpoints to work and allow tracing user + code which handles "Exit" exceptions + + * split off breakpoint code in ruby_debug.c. + + * preface ruby_debug global Ruby variables with rdebug_. + + * Change Debugger.start() to accept an optional options argument + :init => true saves things (like $0 and ARGV) necessary to + allow restart. Default: true + :post_mortem => true runs post-mortem on an uncaught exception + Default: false + + The old Debugger.start() is now renamed to Debugger.start_() + + * split of line caching to an external gem. We now only allow setting + breakpoints on lines where it makes sense to do so. + + * Incompatible enhancement: even return/end will now call event handler + + See ChangeLog for full details, and the reference guide for more complete + documentation of these changes. + +0.10.0 +12/25/07 + +- '-r' option can be used to require additional libraries. +- --noquit option added to stay in debugger when the program exits +- gdb-like --annotate option added. Can be used by front-ends to get information + without polling +- Fixed 'var const' command. Issue #10847. +- Using pretty-print for all var commands. +- Better error reporting for commands that require a numeric argument. +- Fixed Kernel#binding_n method +- Add option -d ($DEBUG = true) and --verbose. Make -v work like ruby. +- Remove debugger messages caused when warnings are turned on. +- "info" and "show" commands added. "set" made more like gdb's + set. subcommands can be abbreviated and are case insensitive. +- restart program if it terminates normally and we've got a tty and + we stop on the first statement. +- help is in tidy column format. method lists are shown that way as well. + the "width" setting ("set/show width") is used for the line width +- stack traces now show parameter names and types. "info args" lists just + the parameters (with the most recent values, not the values at call time). +- post-mortem "exit" bug fixed. +- More Emacs-friendly: rdebug-track.el will track location inside an Emacs + shell. Emacs position information is shown in breakpoints and catchpoints + similar to gdba. Commands to position in another window a unit test traceback + or ruby traceback. Much more work invisioned for Emacs. +- INCOMPATIBLE CHANGE: "break" now sets a breakpoint on the current line + (same as gdb). Use "info break" for a list of breakpoints. +- INCOMPATIBLE CHANGE: "script" command removed. Use "source" command instead + (same as gdb). +- Run .rdebugrc on Debugger.start. Look for a file in the current directory and + run that instead of the one in $HOME if that exists. Again, inspired by and compatible + with gdb. +- Changes compatible with Ruby 1.9. NOTE: this debugger will NOT work with + Ruby 1.9 +- leaving irb shows position same as entering debugger; "list" position + is also cleared when leaving irb +- help "foo" gives message "Undefined command "foo" rather than a list + of help commands. (Message test is gdb's) +- Add set linetrace+ - similar to step+ for linetrace +- Start unit tests. +- Start a reference guide. + +0.9.3 +- Fixed if..elsif..end stepping. +- From irb session Ctrl-C or 'cont' command continues execution without showing the debugger prompt. +- Added Debugger.settings method to programatically modify command settings. +- Added Kernel#breakpoint as alias to Kernel#debugger is the former is not already defined. + +0.9.2 +- Fixed file comparison in Windows platform. +- Added setter methods to Breakpoint properties +- Added breakpoint hit condition functionality (not available via CLI yet) and methods: + Breakpoint:hit_count + Breakpoint:hit_value[=] + Breakpoint:hit_condition[=] + +0.9.1 +- Fixed incorrect stack calculation. +- Context#stop_next= method aliased as Context#step. +- Added the 'force' parameter to Context#step_over. +- Added the 'force' parameter to Context#step. +- 'next+/step+' commands forces to move to another line +- Added a new 'forcestep' setting. + +0.9 +- Kernel#debugger method will start the debugger if it's not running. +- Added Context#stop_reason method. +- Calling a method with a block will create a new frame. This changes the behavior of 'next' command. So in order to step into a block, 'step' command must be used. That fixes bug #9629. +- Added the possibility to add a temporary context-specific breakpoint. Context#breakpoint and Context#set_breakpoint methods are added. +- 'cont' command now accepts a numerical parameter which implements 'Continue until line' behavior. +- Added new Context.frame_class method +- Added new 'framefullpath' setting. +- Added new 'frameclassname' setting. +- All Ruby's 'eval' and require/load methods create a new frame. Fixes bug #9686. + +0.8.1 +- Added a shortcut module 'debugger'. require "ruby-debug/debugger" will start the debugger and stop at the next line (similar to require 'debug'). +- Fixed remote debugging. + +0.8 +- Extract the base debugger API into a separate gem (ruby-debug-base), so it will be easier to add a new interface. +- Added 'set autoirb' setting. +- Bugfixes. + +0.7.5 +- Fixed 'reload on' command +- 'reload on' command is removed in favor of 'set autoreload' +- rdebug will evaluate ~/.rdebugrc script on startup + +0.7.4 +- Added a workaround of the Ruby interpreter problem where a method created with Module#define_method + and which raises an exception doesn't trigger a :return event, this way screwing the stack trace. +- Fixed a situation of an array 'out of bounds' access. +- Fixed the help for 'where' command. + +0.7.3 +- Fixed a case when a frame is not popped up properly. +- Removed Context.ignore= method, since it can result with the segmentation fault error. +- Fixed the case when Context#suspend may effect the state of the thread on Context#resume +- Fixed several cases of seg faults when accessing dyna_vars structure. + +0.7.2 +- Fixed Context#resume (a thread should be waked up only when it was running when it was suspended). +- When handling post-mortem exception, all threads must be suspended. + +0.7.1 +- Fixed 'delete' command + +0.7 +- Eliminated explicit Frame object. Use Context.frame_[binding,file,line] instead. +- Fixed help command. +- Renamed Debugger.keep_frame_info to Debugger.keep_frame_binding +- 'eval' command is available, even when keep_frame_binding is not used. +- New 'set' command is available. + +0.6.2 +- Added thread lookup cache. +- Control thread is always started by rdebug script. +- Ability to specify negative frame number to frame commands. Patch from R. Bernstein. + +0.6.1 +- Another performance optimization. + +0.6 +- Added option to exclude collecting of frame bindings. +- Several performance optimizations. + +0.5.4 +- Added -x/--trace option to rdebug script. Patch from R. Bernstein. +- Removed a live thread reference from the context's structure avoiding memory leakage. + +0.5.3 +- Added Module#post_mortem_method method, which wraps any method with Debugger.post_mortem block. +- Added breakpoint id, which is not dependent on the breakpoint position in Debugger.breakpoints array. + +0.5.2 +- Fixes interoperability problems with rspec. +- Made 'exit' as an alias to 'quit' +- Added 'restart' command. Patch from R. Bernstein. + +0.5.1 +- Bugfixes. + +0.5 +- Added post-mortem debugging +- Added 'irb' command. + +0.4.5 +- Fixed debug_method when applied to setter. +- Added 'reload' command which can be used to reload source code in case it's been changed. +- Added Debugger.reload_source_on_change option (true, by default) which controls whether ruby-debug should keep + track of the source files modification times and reload them if they've been changed. + +0.4.4 +- Renamed Context#set_suspend and Context#clear_suspend methods to Context#suspend and Context#resume respectively. +- Context#resume method not only clears suspend flag, but also resumes the thread execution. +- Bugfixes. + +0.4.3 +- Added Debugger.skip method which allows escaping a block from the debugger reach. +- Bugfixes. + +0.4.2 +- Module#deubg_method added. +- Added rdoc. +- Bugfixes. + +0.4.1 +- New binding_n method for Kernel module. +- Bugfixes. + +0.4 +- Debugger.start method takes a block. If a block is specified, this method starts debugger, yields to the block + and stops debugger at the end. +- 'tm[ate]' command accepts a frame number now. +- 'list' command accepts on/off parameter which controls whether listing will be displayed on every stop. +- 'eval on/off' controls the evaluation of unknown command. +- Debugger reads readline history file .rdebug_hist at startup and saves it at exit. +- 'sa[ve] ' command can be used to save current breackpoints and catchpoint if any +- 'sc[ript] ' command can be used to run script file. Script files can contain only control commands. +- rdebug script accepts '--script FILE' parameter. +- thread commands are available for the control port. + +0.3 (2006-08-07) +- Renamed Debugger.start_server to Debugger.start_remote. +- Debugger.start_remote activates debugger by calling Debugger.start. +- Debugger.start_remote starts a control thread which listen on port 8990 and accepts control + commands, such as adding/deleting breakpoints, assigning catchpoint, etc. (Useful for GUI integration) +- New Debugger.wait_connection option. When it's true, Debugger.start_remote waits until + a remote connection is made. +- New Debugger.stop_on_connect option. When a remote connection is established, debugger + stops the main thread (Thread.main). +- 'interrupt' command is available for the control thread. + +0.2.1 (2006-07-29) +- 'f[rame] nn' command selects a numbered frame. Frame numbers can be obtained by running frame + command without parameters. +- 'l[ist] =' show code in the context of the current line. +- 'tm[ate]' opens the current file in TextMate. Available only on Mac OSX. + +0.2 (2006-07-17) +- Added the remote debugging. It should be activated by calling Debugger#start_server method. +- CHANGED: In order to activate the debugger, it's not enough to require 'ruby-debug'. + Debugger#start method must be called explicitly. +- Debugger used to evaluate anything you enter as long as it's not a command. Starting from + this version the 'eval' command must be used to evaluate an expression. + +0.1.5 (2006-07-13) +- Now the check for a breakpoint uses base filename of the source file. +- Removed compilation warnings when compiling with -Wall + +0.1.4 (2006-07-12) +- Remembers the previous command. Invoke it by typing a carriage return + at the command prompt. + +0.1.3 (2006-07-11) +- Conditional breakpoints +- Bugfixes + +0.1.2 (2006-07-16) +======================== + +- Initial release. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..14748e3 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,5655 @@ +2009-03-29 03:00 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/breakpoints.rb, lib/ChangeLog, + test/data/annotate.right, test/data/breakpoints.right, + test/data/emacs_basic.right, test/data/info.right, + test/data/save.right: Canonicalize breakpoint locations a little + better. More work should be done and more work should be done on + the testing side too. + +2009-03-17 10:35 Rocky Bernstein + + * cli/ruby-debug/commands/irb.rb: Document irb additions old and + new + +2009-03-17 10:33 Rocky Bernstein + + * cli/ruby-debug/commands/irb.rb: irb "next" -> "n" since "next" is + a reserved word. + +2009-03-17 10:30 Rocky Bernstein + + * cli/ruby-debug/commands/irb.rb: Fix some irb -d breakage when set + autoirb is in effect + +2009-03-17 10:22 Rocky Bernstein + + * cli/ruby-debug/commands/irb.rb: Add "next" and "step" commands in + irb + +2009-03-17 02:05 Rocky Bernstein + + * cli/ruby-debug/commands/irb.rb, cli/ruby-debug/processor.rb, + configure.ac, test/data/ctrl.right, test/data/post-mortem.right, + test/test-ctrl.rb: configure.ac: in 0.10.4vc now. Add -d in irb + facilitate debugger testing via global $rdebug_state. Also set + $rdebug_state in debuggertesting is set. + "kill" is now allowed as a control command, this adjusts output. + and this changes + +2009-03-11 23:42 Rocky Bernstein + + * ChangeLog, doc/ruby-debug.texi, lib/ChangeLog: update texinfo for + catch + +2009-03-11 18:57 Rocky Bernstein + + * cli/ruby-debug/commands/catchpoint.rb, emacs/rdebug-core.el, + emacs/rdebug-track.el, emacs/test/test-regexp.el: Update "catch" + command help string. Reindent some emacs files to make tests + happy. + +2009-02-10 04:32 Rocky Bernstein + + * emacs/rdebug-core.el: Remove the annoying disappearing command + window when we there's an initial error in running the Ruby + program + +2009-01-23 20:51 Rocky Bernstein + + * doc/ruby-debug.texi: Show how to add a new command + +2009-01-23 17:20 Rocky Bernstein + + * cli/ruby-debug/commands/kill.rb, cli/ruby-debug/processor.rb: Add + a kill command + +2008-12-24 03:32 Rocky Bernstein + + * test/cli/commands/unit/regexp.rb: One more quit test. + +2008-12-24 03:21 Rocky Bernstein + + * cli/ruby-debug/commands/quit.rb, doc/ruby-debug.texi, + test/cli/commands/unit/regexp.rb, test/data/annotate.cmd, + test/data/annotate.right, test/data/break_bad.cmd, + test/data/break_bad.right, test/data/breakpoints.cmd, + test/data/breakpoints.right: Allow ! suffix on {q{,uit},exit} to + be the same as "unconditionally" #23299 + +2008-11-25 02:43 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/frame.rb, configure.ac, + doc/ruby-debug.texi, ext/ruby_debug.c, lib/ChangeLog, + test/data/frame.cmd, test/data/frame.right: Frame without a frame + number means frame 0, same as gdb. We are now in 0.10.4 territory + now. + +2008-11-17 07:34 Rocky Bernstein + + * CHANGES: Last commit before release. + +2008-11-16 00:14 Rocky Bernstein + + * ChangeLog, bin/rdebug, lib/ChangeLog: Add rdoc for rdebug script. + +2008-11-15 22:13 Rocky Bernstein + + * Rakefile, ext/ruby_debug.c: Go over RDOC documentation. + +2008-11-15 21:51 Rocky Bernstein + + * doc/ruby-debug.texi: Add one more reference to start with a block + +2008-11-15 21:23 Rocky Bernstein + + * doc/ruby-debug.texi: Remove hard-coded version number in example + output + +2008-11-15 02:21 Rocky Bernstein + + * ext/win32/.cvsignore: More administrivia + +2008-11-15 02:20 Rocky Bernstein + + * ext/win32: More administrivia + +2008-11-15 02:18 Rocky Bernstein + + * ., .cvsignore: More administrivia + +2008-11-14 19:39 Rocky Bernstein + + * ., .cvsignore: More administrivia + +2008-11-14 19:38 Rocky Bernstein + + * .cvsignore: Administrivia + +2008-11-14 19:37 Rocky Bernstein + + * ., README, Rakefile, doc, doc/.cvsignore: Go over documentation + for 0.10.3 release. rdoc creates files in doc/rdoc. + +2008-11-14 19:28 Rocky Bernstein + + * README, configure.ac, doc/ruby-debug.texi, + lib/ruby-debug-base.rb: Go over documentation and revise. + +2008-11-14 15:32 Rocky Bernstein + + * CHANGES, ChangeLog, cli/ruby-debug.rb, + cli/ruby-debug/commands/frame.rb, doc/ruby-debug.texi, + ext/ruby_debug.c, lib/ChangeLog, lib/ruby-debug-base.rb: Move + Debugger#debugger from base to cli. Revert code in ruby_debug.c + and block parameter in debugger. cf. -> Compare with. Document + Debugger.start better. + +2008-11-13 10:29 Rocky Bernstein + + * ChangeLog, ext/ruby_debug.c, lib/ChangeLog: Make + Debugger.start{block} work if Debugger.started? is false. Second + try. + +2008-11-11 15:33 Rocky Bernstein + + * ., Rakefile, test/cli/commands/catchpoint_test.rb, + test/cli/commands/unit, test/cli/commands/unit/regexp.rb: Start + unit test for command regular expressions. Much more willing out + to be done later.... + +2008-11-11 14:42 Rocky Bernstein + + * test/data/raise.right: More line number changes in tdebug + +2008-11-11 14:40 Rocky Bernstein + + * test/data/raise.right: tdebug lines have changed + +2008-11-11 02:07 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/frame.rb, lib/ChangeLog, + test/test-dollar-0.rb, test/test-frame.rb, test/trunc-call.rb: + Tweak truncated stack test since Ruby's caller doesn't seem to + include (tail?) recursive calls and we do. Get regression tests + working in light of recent changes. + +2008-11-10 08:47 Kent Sibilev + + * ext/ruby_debug.c: register debug_frame_t->arg_ary with GC + +2008-11-10 02:56 Kent Sibilev + + * bin/rdebug, ext/ruby_debug.c: Trying to fix "if $0 == __FILE__" + ruby's idiom. Apparently setting $0 to + a new value doesn't work correctly. (Ruby's bug?) + + $ cat t3.rb + p $0 + p File.expand_path $0 + $0 = File.expand_path $0 + p $0 + $ ruby t3.rb + "t3.rb" + "/Users/kent/Work/ruby-debug/trunk/t3.rb" + "/Users/ke" + +2008-11-10 01:50 Kent Sibilev + + * ext/ruby_debug.h: added declaration of + check_breakpoints_by_method method to remove compiler warning + +2008-11-10 01:48 Kent Sibilev + + * lib/ruby-debug-base.rb: a little bit more readable + +2008-11-10 01:43 Kent Sibilev + + * ext/ruby_debug.c: running at_exit hooks at the end of the + debug_load method in order to fix test cases a chance to run + +2008-11-10 01:41 Kent Sibilev + + * ext/ruby_debug.c: can't store a copy of the debug_context in the + stack like that, it doesn't play along with garbage collector. + +2008-11-10 01:39 Kent Sibilev + + * ext/ruby_debug.c: these two methods are unused + +2008-11-10 01:36 Kent Sibilev + + * ext/breakpoint.c: fix the compiler warning + +2008-11-10 01:35 Kent Sibilev + + * lib/ruby-debug-base.rb: Debugger.start must always call the + passed block + +2008-11-07 19:35 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/frame.rb, lib/ChangeLog: + Change truncated frame message. + +2008-11-07 10:39 Rocky Bernstein + + * ChangeLog, bin/rdebug, cli/ruby-debug.rb, + cli/ruby-debug/commands/frame.rb, lib/ChangeLog, test/tdebug.rb: + Add check to "where" to see if the call stack is truncated; task + #2354 + +2008-11-06 16:17 Rocky Bernstein + + * ChangeLog, Rakefile, lib/ChangeLog: #22698 Allow ruby-debug-base + 0.x.y.z be compatible with ruby-debug 0.x.y. + +2008-11-02 21:59 Rocky Bernstein + + * ChangeLog, ext/ruby_debug.c, lib/ChangeLog, + lib/ruby-debug-base.rb: Debugger.start with a block now stops + inside the block. Debugger.debugger with a block works like + Debugger.start with a block. + + The whole interface is hopelessly kludgy and needs to be redone. + +2008-10-27 15:29 Rocky Bernstein + + * ChangeLog, test/data/raise.right: tdebug.rb line numbers changed. + Update test numbers -- I think this is right. + +2008-10-26 14:54 Rocky Bernstein + + * ChangeLog, ext/extconf.rb, ext/ruby_debug.c, lib/ChangeLog: Doc + typo. Add comment to remind me how to turn off optimizationin + extconf.rb + +2008-10-25 18:10 Rocky Bernstein + + * cli/ruby-debug/interface.rb: Fix mismatched interface. + +2008-10-25 16:01 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb, ext/ruby_debug.c, + lib/ChangeLog, test/data/annotate.right, + test/data/breakpoints.right, test/data/emacs_basic.right, + test/data/finish.right, test/test-finish.rb: Warn and add a + "confirmation" when setting a breakpoint on a file that is not + loaded. Regression tests no longer fail. + +2008-09-22 21:01 Rocky Bernstein + + * cli/ruby-debug.rb: Remove a $DEBUG warning + +2008-09-22 00:07 Rocky Bernstein + + * doc, doc/.cvsignore, lib/ruby-debug-base.rb, + test/data/pm-bug.cmd, test/data/pm-bug.right, + test/data/post-mortem.right, test/pm-bug.rb, test/test-pm.rb: + #22118 bug in showing variables post mortem. Patch thanks to + rubikitch. + Update pm.rb integration test. + +2008-09-21 23:09 Rocky Bernstein + + * CHANGES: In 0.10.3 territory now. + +2008-09-21 23:06 Rocky Bernstein + + * ext/ruby_debug.c, test/tdebug.rb: tdebug.rb: modify frozen string + taken from rdebug. Patch from Martin Krauskopf. + ruby_debug.c: in 0.10.3 now. + +2008-09-03 17:33 Rocky Bernstein + + * doc: Administrivia + +2008-09-03 17:29 Rocky Bernstein + + * ChangeLog, lib/ChangeLog, test/helper.rb: Show line numbers when + $DEBUG is set. Patch #21772 from Martin Krauskopf + +2008-08-28 05:43 Kent Sibilev + + * ext/ruby_debug.c: + +2008-08-28 05:41 Kent Sibilev + + * CHANGES: preparing version 0.10.2 + +2008-08-15 17:36 Kent Sibilev + + * cli/ruby-debug/commands/list.rb: Fixed an exception when calling + Kernel#debugger method from the eval code + +2008-07-10 09:47 Kent Sibilev + + * cli/ruby-debug/commands/continue.rb, cli/ruby-debug/processor.rb: + allow 'continue' command from post-mortem + + here is an example where it is needed: + + ... + Debugger.post_mortem do + method_that_raises_an_exception() + end + ... + + I want to be able to inspect the post_mortem context and then to + continue the program execution + +2008-07-10 08:55 Kent Sibilev + + * ext/ruby_debug.c: fixed segfault and finish command + +2008-07-09 19:43 Kent Sibilev + + * cli/ruby-debug/commands/breakpoints.rb: allow setting a + breakpoint on a file that is not yet loaded + +2008-07-09 19:29 Kent Sibilev + + * cli/ruby-debug/interface.rb: RemoteInterface should extend + Interface class + +2008-07-09 19:25 Kent Sibilev + + * bin/rdebug: $0 is frozen in Ruby 1.8.7 + +2008-07-09 00:43 Rocky Bernstein + + * cli/ruby-debug.rb, cli/ruby-debug/processor.rb: Some meager (and + not complete) support for a verbose mode on + source'ing a file. Some more print's turned to errmsg as + appropriate. + +2008-07-07 07:11 Rocky Bernstein + + * lib/ruby-debug-base.rb: Tracker [#20041] start erroneously moved + to Kernel - should be in + Debugger.start + +2008-07-03 16:03 Rocky Bernstein + + * doc/ruby-debug.texi: Document that backslash can escape debugger + command separation. + +2008-06-20 06:46 Rocky Bernstein + + * CHANGES, cli/ruby-debug/commands/trace.rb, + lib/ruby-debug-base.rb: trace.rb: add "trace var" + ruby-debug-base.rb: remove another undefined warning. + +2008-05-27 03:54 Rocky Bernstein + + * cli/ruby-debug/commands/save.rb, cli/ruby-debug/interface.rb, + test/data/save.cmd, test/data/save.right, test/test-save.rb: Add + save test. save.rb: use pretty-printed regexp. Interface, for now + add restart_file accessor like the others. The processor + interface + need revision though. + +2008-05-24 01:27 Rocky Bernstein + + * ChangeLog, doc/ruby-debug.texi, lib/ChangeLog: Remove dup lines. + +2008-05-23 14:57 Rocky Bernstein + + * cli/ruby-debug/commands/save.rb: Catchpoints have changed. Fix + bug in saving them. + +2008-05-23 01:04 Rocky Bernstein + + * cli/ruby-debug/commands/catchpoint.rb, + cli/ruby-debug/commands/info.rb, ext/breakpoint.c, + test/cli/commands/catchpoint_test.rb, test/data/catch.cmd, + test/data/catch.right, test/test-catch.rb: Lots of bogosity fixed + in catchpoint handling. Added "catch xxx off". + Confirm when deleting all catchpoints. Correct C rdoc. + #20237 + +2008-05-20 07:20 Rocky Bernstein + + * doc/rdebug-emacs.texi, doc/ruby-debug.texi: Use a straight quote + in the typewriter font. + +2008-05-17 22:11 Rocky Bernstein + + * cli/ruby-debug/commands/save.rb: Wording a little closer to gdb's + ;-) + +2008-05-17 11:35 Rocky Bernstein + + * doc/rdebug-emacs.texi, doc/ruby-debug.texi: e.g. -> e.g.@: + +2008-05-15 18:06 Rocky Bernstein + + * test, test/.cvsignore: Ignore config.private.yaml which folks may + use/customize to omit tests + +2008-05-15 17:52 Rocky Bernstein + + * Rakefile, test/cli, test/cli/commands, + test/cli/commands/catchpoint_test.rb: Regression test for recent + "catch nn off" error. Again from Martin Krauskopf + +2008-05-15 16:05 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/catchpoint.rb, lib/ChangeLog: + Handle "catch nnn off" Forgotten there during r656. + From mkrauskopf [#20156]. + +2008-05-12 03:21 Rocky Bernstein + + * cli/ruby-debug/commands/irb.rb: Small doc fix. + +2008-05-11 15:25 Rocky Bernstein + + * test/data/raise.right: tdebug.rb got a line shorter. + +2008-05-11 09:03 Rocky Bernstein + + * test/helper.rb, test/test-init.rb: Patch #19934 multi-interpreter + patch from Martin Krauskopf + +2008-05-11 08:38 Rocky Bernstein + + * bin/rdebug, ext/ruby_debug.c, test/data/output.right, + test/data/quit.right, test/tdebug.rb: Remove stop in debug_load + due to Debugger.start getting called twice. + The fix -- for now -- is to add another parameter to debug_load + to + indicate not to increment debug_count. We could also make that + the + default in debug_load as well, but debug_load might be useful in + other + situations and where control_threads are not relevant (which is + why we + need to call Debugger.start rather than let debug_load do it). + + Bug #19930 + +2008-05-05 18:05 Rocky Bernstein + + * ChangeLog, lib/ChangeLog, test/data/frame.right, + test/test-frame.rb: make test-frame installation independent. Bug + #19931 + +2008-05-01 23:16 Rocky Bernstein + + * doc/ruby-debug.texi: Remove a Texism. texinfo does not do or need + italic correction. + +2008-04-30 20:14 Rocky Bernstein + + * doc/ruby-debug.texi: Fix doc for binding_n(). + +2008-04-29 14:00 Rocky Bernstein + + * cli/ruby-debug/commands/method.rb, doc/ruby-debug.texi, + test/classes.rb, test/data/methodsig.right: Small doc and test + improvements on 'method signature' + +2008-04-29 13:37 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/continue.rb, lib/ChangeLog, + test/data/frame.cmd, test/data/frame.right: Test line number in + "continue" command for validity. + +2008-04-29 09:11 Rocky Bernstein + + * cli/ruby-debug/commands/method.rb, + cli/ruby-debug/commands/set.rb, + cli/ruby-debug/commands/variables.rb, test/classes.rb, + test/data/method.cmd, test/data/method.right, + test/data/methodsig.cmd, test/data/methodsig.right, + test/data/setshow.right, test/test-method.rb: Add "method + signature" command to show a method's signature. + +2008-04-29 08:23 Rocky Bernstein + + * test/config.yaml: Forgot to add this on last commit. + +2008-04-28 16:42 Rocky Bernstein + + * cli/ruby-debug/commands/set.rb, test/data/setshow.cmd, + test/data/setshow.right: Catch errors in improper set callstyle + parameter. Bug #19792 + +2008-04-28 16:16 Rocky Bernstein + + * ChangeLog, lib/ChangeLog, test/helper.rb: From Martin Krauskopf + via patch #19779 + + Allow folks to configure Ruby used for CLI tests in the + test/config.yaml. The defaults are for native Ruby, so nothing + needs + to be done for ruby-debug. + + Developers of interfaces other than cli might override + config.yaml by + customized config.private.yaml which is ignored. So there will be + no + trash in e.g. 'svn st' output when developer customize the Ruby + to be + used. + + Handy for alternative interface implementations using + svn:externals. + +2008-04-27 08:28 Rocky Bernstein + + * emacs/rdebug-cmd.el, emacs/rdebug-track.el: Reduce spurious + read-only setting when short-key is turned + on/off in the command buffer. + +2008-04-25 02:54 Rocky Bernstein + + * CHANGES, emacs/rdebug-cmd.el, emacs/rdebug-gud.el, + emacs/rdebug-source.el, emacs/rdebug-track.el: Try to get + rdebug-track under control again. + Remove "<" in the command buffer as a local key setting. + Make more checkdoc friendly. + +2008-04-22 02:49 Rocky Bernstein + + * doc/ruby-debug.texi, lib/ruby-debug-base.rb: Experiment with + debugger(steps=0). Puts us in the debugger call, but this may be + the best we can do for now. See tracker + #19639. + +2008-04-20 21:38 Rocky Bernstein + + * doc/rdebug-emacs.texi, doc/ruby-debug.texi: rdebug-emacs.texi: + update nodes so makeinfo will work. + rdebug-texi: Note slight preference for ruby -rtracer over rdebug + --trace. + +2008-04-19 13:22 Rocky Bernstein + + * ext/ruby_debug.c, test/bp_loop_issue.rb, + test/data/break_loop_bug.cmd, test/data/break_loop_bug.right, + test/data/breakpoints.cmd, test/data/breakpoints.right, + test/data/emacs_basic.right, test/test-break-bad.rb, + test/test-emacs-basic.rb: Change test for whether we have moved + off a line or not for purposes + of stopping at a breakpoint on a line. The line events for which + there + are normally two stops are on NODE if's before the if and after + the + expression evaluation. Tracker #19594. + +2008-04-16 01:11 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/show.rb, + cli/ruby-debug/interface.rb, cli/ruby-debug/processor.rb, + ext/ruby_debug.c, lib/ChangeLog, test/data/setshow.cmd, + test/data/setshow.right: In 0.10.2 now. Some work to cope systems + without readline. More work is needed. + Add test of "set autoeval." Undefined command message more + closely like gdb's. + +2008-04-15 23:56 Rocky Bernstein + + * doc/ruby-debug.texi: Note that Debugger.start is currently broken + when used with a block. + +2008-04-11 22:24 Anders Lindgren + + * doc/rdebug-emacs.texi: Section on 'customize' added. + +2008-04-10 08:49 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/command.rb, lib/ChangeLog: linecache is + required by ruby-debug-base not ruby-debug. Thanks Martin! + +2008-04-10 08:00 Rocky Bernstein + + * ChangeLog, Rakefile, lib/ChangeLog: Last change before 0.10.1 + release. + +2008-04-10 02:03 Rocky Bernstein + + * ChangeLog, doc/rdebug-emacs.texi, lib/ChangeLog: Cosmetic stuff: + spelling corrections. Update node structure so texinfo + doesn't complain. + +2008-04-09 21:22 Anders Lindgren + + * doc/rdebug-emacs.texi: New chapter for multi-window debugging. + Intro reworked. NOTE: Menu nodes not updated. + +2008-04-08 19:55 Anders Lindgren + + * emacs/rdebug-shortkey.el, emacs/test/test-shortkey.el: Logic in + rdebug-internal-short-key-mode reworked. Test case updated. + +2008-04-08 14:52 Rocky Bernstein + + * ChangeLog, Rakefile, lib/ChangeLog: autorequire is deprecated and + presumably no longer needed + http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/182827 + +2008-04-08 14:16 Rocky Bernstein + + * test/data/raise.right: Another test data line number change + +2008-04-08 14:12 Rocky Bernstein + + * test/tdebug.rb: tdebug.rb alignment with rdebug + +2008-04-08 14:02 Rocky Bernstein + + * test/data/linetracep.cmd: Forgot to add this for the linetrace+ + test. + +2008-04-08 14:01 Rocky Bernstein + + * emacs/rdebug-shortkey.el, emacs/test/test-shortkey.el: Attempt a + fix at shortkey internal. There be dragons here. Not sure what's + going on. + +2008-04-08 10:23 Rocky Bernstein + + * test/data/linetracep.right, test/test-trace.rb: Another linetrace + test. This time with linetrace+ set. + +2008-04-08 10:19 Rocky Bernstein + + * cli/ruby-debug/processor.rb, test/data/linetrace.cmd, + test/data/linetrace.right, test/test-trace.rb: processor.rb: + Silence possibly more warnings under $DEBUG + test/*: another linetrace test using the linetrace command. + +2008-04-08 03:17 Rocky Bernstein + + * test/data/output.right, test/data/quit.right: Test line numbers + changed. Sigh + +2008-04-08 03:14 Rocky Bernstein + + * test/tdebug.rb: Track rdebug. + +2008-04-08 03:10 Rocky Bernstein + + * test/test-trace.rb: Oops forget this test + +2008-04-08 03:09 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/processor.rb, test/data/trace.right, + test/tdebug.rb: Fix bug in --trace. Add regression test for that + as well. + Reduce (but alas not eliminate) extraneous line tracing. + +2008-04-07 00:36 Rocky Bernstein + + * CHANGES, ChangeLog, emacs/Makefile.am, emacs/rdebug-shortkey.el, + emacs/test/test-shortkey.el, lib/ChangeLog, + lib/ruby-debug-base.rb: ruby-debug-base.rb: document + Debugger.start parameters. + CHANGES: Revise what's happened + test-shortkey.el: A failing regression test because I think + rdebug-shortkey-mode + is not correct. + +2008-04-06 03:03 Rocky Bernstein + + * bin/rdebug, test/data/test-init-cygwin.right, test/test-init.rb: + Assigning $0 on cygwin seems weird. cygwin readline different too + +2008-04-06 02:13 Rocky Bernstein + + * test/data/test-init-osx.right, test/test-init.rb: read_command on + OSX seems to work differently. Punt for now. + +2008-04-04 19:22 Rocky Bernstein + + * cli/ruby-debug/commands/eval.rb: Sometimes remove_method isn't + defined. + +2008-04-03 19:13 Rocky Bernstein + + * doc/ruby-debug.texi: Small typos. + +2008-04-03 19:01 Rocky Bernstein + + * ChangeLog, doc/ruby-debug.texi, lib/ChangeLog, + lib/ruby-debug-base.rb, test/pm-base.rb: Allow setting + :post_mortem => true from Debugger.start. + +2008-04-03 14:22 Rocky Bernstein + + * Rakefile: We'll require linecache 0.4 or better. (Use SVN for + now. Will be released at same time as ruby-debug). + +2008-04-03 14:15 Rocky Bernstein + + * test/data/annotate.cmd, test/data/annotate.right, + test/data/post-mortem-osx.right, test/test-pm.rb: test-pm.rb, + post-mortem-osx.right: Allow for tmate command on OSX. + annotate.*: make sure 'set force on' doesn't happen. + +2008-04-03 12:06 Rocky Bernstein + + * cli/ruby-debug/commands/irb.rb: irb is no longer 'experimental'. + +2008-04-02 00:50 Rocky Bernstein + + * emacs/rdebug-annotate.el, emacs/rdebug-core.el, + emacs/rdebug-shortkey.el: Auto indent. + +2008-04-02 00:27 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-shortkey.el: Short-key mode is + turning itself on rather than off sometimes. More control over + trying to get rid of it when desired. + +2008-03-30 03:01 Rocky Bernstein + + * doc/ruby-debug.texi: Note that rdebug with test/unit might work. + +2008-03-28 13:53 Rocky Bernstein + + * ChangeLog, emacs/rdebug-annotate.el, lib/ChangeLog: Don't + unconditionally turn on short-key mode when annotations are on. + Use rdebug-short-key-mode setting to decide. + +2008-03-23 17:47 Rocky Bernstein + + * ChangeLog, Rakefile, cli/ruby-debug/commands/set.rb, + cli/ruby-debug/commands/settings.rb, lib/ChangeLog: set.rb -> + settings.rb since it's already one command per file, and + remove another :nodoc. + Rakefile: split long line + +2008-03-23 04:12 Rocky Bernstein + + * cli/ruby-debug/commands/show.rb, emacs/rdebug-core.el: + rdebug-core.el: allow rdebug-reset as an emasc command + show.rb: remove one more :nodoc + +2008-03-21 19:04 Rocky Bernstein + + * emacs/rdebug-breaks.el, emacs/rdebug-core.el, + emacs/rdebug-gud.el, emacs/test/test-cmd.el: Regularize names a + little bit. More work is needed though. + +2008-03-21 18:39 Rocky Bernstein + + * emacs/rdebug-breaks.el, emacs/rdebug-gud.el: Clear breakpoint + icons when quitting the debugger. + +2008-03-19 19:56 Rocky Bernstein + + * doc/ruby-debug.texi: more on --keep-frame-binding (for Martin) + +2008-03-19 15:07 Rocky Bernstein + + * cli/ruby-debug/commands/list.rb, test/data/list.cmd, + test/data/list.right, test/data/raise.right: Fix bug in "list -": + was scrolling back to negative lines. Had also been skipping + lines in forward list. + +2008-03-19 07:36 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb: remove 'nodoc' (and doc) from + InfoCommand class + +2008-03-19 07:31 Rocky Bernstein + + * doc/rdebug-emacs.texi: Spelling correction. + +2008-03-19 00:44 Rocky Bernstein + + * doc/ruby-debug.texi: Some more spelling corrections. + +2008-03-19 00:27 Rocky Bernstein + + * doc/ruby-debug.texi: Spell-checking corrections. + +2008-03-18 19:47 Rocky Bernstein + + * CHANGES: Try to make more readible. + +2008-03-18 16:05 Rocky Bernstein + + * CHANGES, ChangeLog, cli/ruby-debug/commands/list.rb, + lib/ChangeLog, test/data/list.cmd, test/data/list.right, + test/test-finish.rb, test/test-list.rb: Fix bug in 'list' command + when wrapping off the end. + test-finish.rb: tolerate buggy in Ruby versions <= 1.8.7. + +2008-03-18 00:43 Rocky Bernstein + + * cli/ruby-debug/commands/list.rb, + cli/ruby-debug/commands/reload.rb: Split off reload into its own + file. + +2008-03-17 14:29 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-annotate.el, emacs/rdebug-cmd.el, + emacs/rdebug-fns.el, emacs/rdebug-locring.el, + emacs/rdebug-shortkey.el, emacs/rdebug-source.el, + emacs/rdebug-track.el, emacs/rdebug-vars.el, + emacs/test/test-fns.el: Regularize location ring function names. + +2008-03-17 04:03 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/stepping.rb, + test/data/stepping.right: stepping.rb: don't step if invalid + parameter + command.rb: remove dupliate defined warning msg + +2008-03-17 03:34 Rocky Bernstein + + * cli/ruby-debug/commands/stepping.rb: Small doc addition + +2008-03-17 03:17 Rocky Bernstein + + * cli/ruby-debug/commands/source.rb: Make source file-not-found and + error + +2008-03-17 03:07 Rocky Bernstein + + * cli/ruby-debug/commands/source.rb: tidy regexp + +2008-03-17 03:05 Rocky Bernstein + + * cli/ruby-debug/commands/script.rb, + cli/ruby-debug/commands/source.rb: Rename to match command name. + Add miniscule doc. + +2008-03-16 22:04 Rocky Bernstein + + * cli/ruby-debug/commands/continue.rb, + cli/ruby-debug/commands/frame.rb, doc/ruby-debug.texi: Doc + changes + +2008-03-16 16:38 Rocky Bernstein + + * doc/ruby-debug.texi, test/base/base.rb, test/base/catchpoint.rb, + test/base/load.rb: Add debug_load test. Document + Debugger::Context better. Small doc changes. + +2008-03-16 15:01 Rocky Bernstein + + * bin/rdebug: Typo. + +2008-03-16 07:39 Rocky Bernstein + + * cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/help.rb: Minor doc changes + +2008-03-16 06:50 Rocky Bernstein + + * test/data/ctrl.cmd, test/data/ctrl.right: Make sure width is set + explicitly so we don't have vagaries of the environment. + +2008-03-16 06:44 Rocky Bernstein + + * test/data/stepping.cmd, test/data/stepping.right: Possibly patch + change to upcoming 1.8.7. Punt for now. + +2008-03-16 04:03 Rocky Bernstein + + * CHANGES, cli/ruby-debug/commands/finish.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/quit.rb, doc/ruby-debug.texi, + test/data/breakpoints.cmd, test/data/breakpoints.right, + test/data/finish.cmd, test/data/finish.right, + test/test-finish.rb: Change finish with no args to finish out of + the currently selected + frame and document that. + Add test for "finish" command. + ruby-debug.texi: Note 2nd-hook eval bug in "if" statements. + + ruby-debug.texi: + +2008-03-13 02:15 Rocky Bernstein + + * CHANGES, cli/ruby-debug/commands/finish.rb, + cli/ruby-debug/processor.rb, doc/ruby-debug.texi, + ext/ruby_debug.c, lib/ruby-debug-base.rb, rdbg.rb: INCOMPATIBLE + CHANGE: "finish" works like gdb - stop just before the + most recent method finishes. Will now accept a number which stops + that + many frames completed. (Note that return line numbers will be + funny, + the first line of the method until Ruby 1.8.7.) + +2008-03-11 03:53 Rocky Bernstein + + * test/base/base.rb, test/base/catchpoint.rb: Reduce unnecessary + dependencies and scope. + +2008-03-10 14:51 Rocky Bernstein + + * cli/ruby-debug/commands/catchpoint.rb, + cli/ruby-debug/commands/info.rb: "catch" is same as "info catch". + Document better "catch" command. + +2008-03-10 13:28 Rocky Bernstein + + * ChangeLog, lib/ChangeLog, test/data/raise.right: Dunno why we are + now one line number less. So be it (for now). + +2008-03-10 11:42 Rocky Bernstein + + * cli/ruby-debug/commands/continue.rb, + cli/ruby-debug/commands/finish.rb, + cli/ruby-debug/commands/stepping.rb, cli/ruby-debug/processor.rb: + Break out finish.rb and continue.rb from stepping.rb + +2008-03-09 23:30 Rocky Bernstein + + * CHANGES, ChangeLog, lib/ChangeLog, test/data/info.right: For now + we require the duplicate numbers on conditionals. + +2008-03-09 23:25 Rocky Bernstein + + * Rakefile: Need at least linecache 0.3 now. Probably 0.4 for + release. + +2008-03-07 04:26 Rocky Bernstein + + * Rakefile, bin/rdebug, doc/ruby-debug.texi, test/test-dollar-0.rb: + Use ~/.rdboptrc (rdbopt.ini on MS Windows) to change default + options. + +2008-03-03 04:14 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/quit.rb: Split off quit to it's own file + since it doesn't share code with the + reset of "control". Smaller is better and it helps deal with + meeting + in the middle for extending debug 1.9 code. + +2008-03-03 01:50 Rocky Bernstein + + * cli/ruby-debug/commands/stepping.rb, test/data/stepping.cmd, + test/data/stepping.right: Allow spaces at the end of step and + next. Test ";" between commands. + +2008-03-02 16:45 Rocky Bernstein + + * CHANGES, cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/threads.rb, doc/ruby-debug.texi, + test/data/frame.cmd, test/data/frame.right: Add ability to + specify a thread number in a "frame" command. + +2008-03-02 13:47 Rocky Bernstein + + * doc/ruby-debug.texi: Add Instructions for building on Microsoft + Windows. + +2008-03-02 13:07 Rocky Bernstein + + * doc/ruby-debug.texi: Small typo. + +2008-03-02 04:20 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb, lib/ruby-debug-base.rb, + test/base/base.rb, test/data/breakpoints.right, + test/data/emacs_basic.right: Better error message for an invalid + break command. + +2008-03-02 03:32 Rocky Bernstein + + * emacs/rdebug-cmd.el: Bug in wrapping to newest in + rdebug-older-location. + +2008-03-02 02:48 Rocky Bernstein + + * test/base/base.rb, test/base/binding.rb, test/gcd-dbg-nox.rb: + Small changes. Use unshift instead of << and Remove from $: after + done. + base.rb: Debugger.start -> Debugger.start_ + +2008-03-02 02:24 Rocky Bernstein + + * doc/Makefile.am, doc/rdebug-emacs.texi, doc/ruby-debug.texi: + Split emacs stuff into it's own document. Right now this makes + things + worse. Hopefully the benefit over time will outweigh this. + +2008-03-01 11:36 Rocky Bernstein + + * doc/ruby-debug.texi: Go over post-mortem section. Note the + weirdness concerning breakpoint + file names and how to scope out how to fix. + +2008-03-01 03:39 Rocky Bernstein + + * emacs/rdebug-cmd.el: Add message when wrapping source location + position. Not sure if this is right. We'll see. + +2008-02-29 15:24 Rocky Bernstein + + * emacs/rdebug-cmd.el, emacs/rdebug-frames.el: Fix bug in + rdebug-older-location when ring is empty - index -1. + Set rdebug-frames-current-frame-number variable in comint buffer + which is + needed at least for source location history processing. + +2008-02-29 10:41 Rocky Bernstein + + * emacs/rdebug-cmd.el: Remove gud-gdb-complete command for now. + +2008-02-29 04:34 Rocky Bernstein + + * emacs/rdebug-cmd.el, emacs/rdebug-fns.el, emacs/rdebug-frames.el, + emacs/rdebug-gud.el, emacs/rdebug-secondary.el, + emacs/rdebug-source.el: Wrap when ad top stack frame and trying + to go to a newer one. I think + the bindings for "<" and ">" were reversed. Some checkdoc + warnings addressed. + +2008-02-29 01:33 Rocky Bernstein + + * emacs/rdebug-track.el: Try to make more like rdebug. Get + M-up/M-down working. + Need to revisit this code and rdebug-core to understand, unify, + and simplify + more. + +2008-02-28 20:04 Rocky Bernstein + + * emacs/rdebug-core.el: For the bogus-buffer, use something less + computationally intensive. + +2008-02-28 05:06 Rocky Bernstein + + * ChangeLog, emacs/rdebug-core.el, emacs/rdebug-fns.el, + lib/ChangeLog, test/data/breakpoints.cmd, + test/data/breakpoints.right: breakpoints.{cmd,right}: test for an + invalid stopping line number + rdebug-fns.el: move generic split-string-and-unquote from + rdebug-core. + rdebug-core.el: Add rdebug-common-init to replace + gud-common-init. Is + simpler, and finds files better via debugger output/annotations. + Fix bug in rdebug-setup-windows: gud-find-file can return nil, + and + we still need to set buf. + +2008-02-27 04:04 Rocky Bernstein + + * lib/ruby-debug-base.rb: Slightly more robust handle_post_mortem. + +2008-02-26 17:31 Rocky Bernstein + + * ChangeLog, emacs/rdebug-cmd.el, emacs/rdebug-fns.el, + emacs/rdebug-source.el, emacs/rdebug-vars.el, + emacs/test/test-fns.el, lib/ChangeLog: Go over source location + positioning. 0 is now the oldest (first) position. Add M-S-down + and M-S-up for first and last. More tests needed in test-fns.el + and need to prompt on wrap around. + +2008-02-26 00:57 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/info.rb, lib/ChangeLog, + test/data/info.cmd, test/data/info.right: Fix bug in "info file + xxx breakpoints". + +2008-02-25 12:39 Rocky Bernstein + + * cli/ruby-debug/interface.rb: File.exists? -> File.exist? for Ruby + 1.9 + +2008-02-24 16:36 Rocky Bernstein + + * ChangeLog, bin/rdebug, lib/ChangeLog: rdebug; make more Ruby 1.9 + compatible. + +2008-02-24 16:14 Rocky Bernstein + + * ChangeLog, bin/rdebug, emacs/rdebug-regexp.el, lib/ChangeLog, + rdbg.rb: Minor changes. + rdbg.rb: don't need $DEBUG test any more + rdebug-regexp.el: go over with checkdoc + bin/rdebug: use PATH_SEPARATOR (for 'doze again) + +2008-02-24 04:51 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/info.rb, doc/ruby-debug.texi, + emacs/rdebug-fns.el, emacs/rdebug-layouts.el, + emacs/rdebug-secondary.el, emacs/rdebug-track.el, + emacs/test/test-fns.el, lib/ChangeLog, test/data/help.cmd, + test/data/help.right, test/test-help.rb: CLI: Add long help for + "info file". + + test/test-help.rb: Make test failures easier to fix and more like + the + other tests. + + emacs/test: finish testing all of the funcitons in rdebug-fns.el + + rdebug-layouts.el: Make checkdoc clean. + rdebug-track.el: don't need to rename shell buffer. Do it as an + option only. + rdebug-secondary.el: get rid of hoaky buffer finding for at least + gud-comint-buf. (Should probably do others as well) + + DOC: Note weird line stopping locations. Describe what "ctrl" in + prompt means. + +2008-02-23 21:55 Rocky Bernstein + + * emacs/rdebug-fns.el, emacs/test/test-fns.el: More stringent test + on rdebug-data-process-p. Add a unit test of this too. At least a + start at one. + +2008-02-22 12:57 Rocky Bernstein + + * emacs/rdebug-annotate.el: Make gud-last-frame buffer local to all + secondary buffers. + +2008-02-22 12:44 Rocky Bernstein + + * emacs/rdebug-frames.el: Set source frame arrow type (top or not) + in processing the stack frame + annotation. Even though there is another setting in the anotation + filter hook, we can't remove it in main annotation filter because + we + can't assume annotate=3. + +2008-02-22 09:31 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb: Need to handle glob expansion + in program script on restart. + File.exists? -> File.exist? + +2008-02-22 06:50 Anders Lindgren + + * emacs/rdebug-annotate.el, emacs/rdebug-core.el, + emacs/rdebug-vars.el: Process status is now in color. Renamed + rdebug-mode-line-status to rdebug-inferior-status to be more like + gdb-ui. Moved some complexity from rdebug-mode-line-process to a + new function rdebug-display-inferior-status. + +2008-02-22 02:40 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-fns.el, emacs/rdebug-gud.el, + emacs/rdebug-track.el, emacs/test/test-cmd.el: Add some error + checking around gud-call - like dead or nonexistent process. + Set gud-comint-buffer for rdebug-track + rdebug-call -> rdebug-call-return. rdebug-call is just the call + part. + +2008-02-21 19:26 Rocky Bernstein + + * emacs/rdebug-annotate.el, emacs/rdebug-cmd.el, + emacs/rdebug-shortkey.el: A couple of (if .. (progn ...)) turned + into (when ...). + +2008-02-21 19:00 Rocky Bernstein + + * emacs/rdebug-annotate.el, emacs/rdebug-fns.el, + emacs/rdebug-track.el: More work on the simple rdebug-track mode + with respect to location + ring handling. A couple of out-and-out bugs removed. + +2008-02-21 16:27 Rocky Bernstein + + * emacs/rdebug-annotate.el, emacs/rdebug-cmd.el, + emacs/rdebug-fns.el, emacs/rdebug-gud.el, emacs/rdebug-track.el: + Bang on rdebug-track.el to get to work better. Basically added + gud-call-frame, + position tracking and more common initialization for key + bindings. + +2008-02-21 02:56 Rocky Bernstein + + * ChangeLog, emacs/Makefile.am, emacs/rdebug-annotate.el, + emacs/rdebug-error.el, emacs/rdebug-fns.el, + emacs/rdebug-frames.el, emacs/rdebug-vars.el, + emacs/test/test-error.el, emacs/test/test-fns.el, + emacs/test/test-indent.el, lib/ChangeLog: Fringe for frame buffer + the same as in source code. Move + miscellaneous small functions to a new file. Reduce duplication + of + "chomp" code. + +2008-02-20 17:16 Anders Lindgren + + * emacs/rdebug-annotate.el: Process status is now 'running', + 'stopped', 'exited', and 'crashed'. (Detecting the crash + situation is a hack, the prompt is checked if it contains + 'post-mortem'...) + +2008-02-20 07:09 Anders Lindgren + + * emacs/rdebug-annotate.el, emacs/rdebug-breaks.el, + emacs/rdebug-core.el, emacs/rdebug-error.el, + emacs/rdebug-frames.el, emacs/rdebug-help.el, + emacs/rdebug-info.el, emacs/rdebug-output.el, + emacs/rdebug-source.el, emacs/rdebug-varbuf.el, + emacs/rdebug-vars.el, emacs/rdebug-watch.el: Debugger status is + now displayed in the mode line of source and secondary buffers. + +2008-02-19 23:44 Rocky Bernstein + + * CHANGES, ChangeLog, bin/rdebug, emacs/rdebug-cmd.el, + lib/ChangeLog: rdebug-cmd.el: M-insert toggles shortkey mode in + the command buffer + rdebug: search for Ruby program if file is not found and no + SEPARATOR + chars in the filename + +2008-02-19 15:20 Rocky Bernstein + + * cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, doc/ruby-debug.texi, + test/data/ctrl.right: Add "show post-mortem". Note "show port" + now requires 3 letters: "show por" + to distinguish it from "show post-mortem". + +2008-02-19 13:56 Rocky Bernstein + + * cli/ruby-debug/interface.rb, cli/ruby-debug/processor.rb, + emacs/rdebug-track.el: remove annotate=2. Emacs code can now + redirect output to command or to buffer. + rdebug-track.el + +2008-02-18 19:56 Rocky Bernstein + + * ChangeLog, emacs/rdebug-annotate.el, lib/ChangeLog: Frame + switching shouldn't be recorded in position history ring. + +2008-02-18 04:49 Rocky Bernstein + + * emacs/rdebug-annotate.el, emacs/rdebug-frames.el, + emacs/rdebug-shortkey.el, emacs/rdebug-vars.el: Make + gud-comint-buffer local in the source file. + Frame indicator is hollow except when it's the top frame. + +2008-02-17 23:51 Rocky Bernstein + + * doc/emacs-notes.txt: Note as to how some of the emacs code is + structured. + +2008-02-17 22:45 Anders Lindgren + + * emacs/test/test-annotate.el: Fixed broken case (rdebug-call-queue + is now a list of lists). + +2008-02-17 22:42 Anders Lindgren + + * emacs/rdebug-annotate.el: Exit messages now go to the echo area. + New command kind supported in rdebug-call-queue, :message. + +2008-02-17 22:00 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-annotate.el, emacs/rdebug-dbg.el, + emacs/rdebug-info.el, emacs/rdebug-shortkey.el, + emacs/rdebug-source.el, emacs/test/test-annotate.el, + emacs/test/test-filter.el, emacs/test/test-frames.el, + emacs/test/test-regexp.el: test-filter.el -> test-annotate.el + Reinstate the ";;; redebug-xxx.el ends here" and ;;; + rdebug-xxx.el --- at the + thop. + +2008-02-17 21:25 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-shortkey.el, + emacs/rdebug-source.el: Move short-key mode from source into + short-key. + Makefile.am: reduce redundancy a tad. + +2008-02-17 17:52 Rocky Bernstein + + * emacs/rdebug-annotate.el, emacs/rdebug-breaks.el, + emacs/rdebug-core.el, emacs/rdebug-frames.el, + emacs/rdebug-help.el, emacs/rdebug-info.el, + emacs/rdebug-output.el, emacs/rdebug-regexp.el, + emacs/rdebug-varbuf.el, emacs/rdebug-watch.el: Replace + rdebug--... with rdebug-. Run checkdoc and deal with some of + those errors. + +2008-02-17 14:56 Anders Lindgren + + * emacs/rdebug-annotate.el, emacs/rdebug-gud.el, + emacs/rdebug-info.el, emacs/rdebug-vars.el: The rdebug-call-queue + system reworked, each entry is now a list of the + command and options telling the system what it should do with the + output. Currently, :tooltip and :info are supported, but more can + easily be added (including support for lambda-expression, if + needed). + + The info buffer now only displays things if explicitly asked to + do so. + + Two proof-of-concept functions added, + rdebug-pretty-print-to-buffer + and rdebug-pretty-print-region-to-buffer. Note that the user + interface + might differ in the future (we don't want too many user-level + function.) + + The info buffer is no longer treated as accumulative, this + simplifies + the rdebug-cmd-XXX functions, but the user has to wait until the + command has terminated until the output is displayed in the info + buffer. + +2008-02-17 13:57 Rocky Bernstein + + * CHANGES, cli/ruby-debug/commands/info.rb, doc/ruby-debug.texi, + lib/ruby-debug-base.rb, test/data/post-mortem.right: Add + Debugger.last_exception. Show exception in post-mortem when "info + program" + is issued. Reorganize list of major changes better. + +2008-02-17 10:35 Rocky Bernstein + + * emacs/rdebug-breaks.el: Improve comment. + +2008-02-17 10:32 Rocky Bernstein + + * emacs/rdebug-breaks.el: Remove rdebug-test-test which doesn't + seem to be used. + +2008-02-17 03:57 Rocky Bernstein + + * emacs/rdebug-breaks.el, emacs/rdebug-core.el: Move some + breakpoint-related code from rdebug-core.el to rdebug-breaks.el + +2008-02-17 02:40 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-annotate.el, + emacs/rdebug-breaks.el, emacs/rdebug-cmd.el, + emacs/rdebug-core.el, emacs/rdebug-error.el, + emacs/rdebug-info.el, emacs/rdebug-shortkey.el, + emacs/rdebug-vars.el, emacs/test/test-error.el, + emacs/test/test-filter.el, emacs/test/test-regexp.el: Create + functions for showing temporary messages and error messages - + don't call show-tooltip() or message() directy. + + Break out annotations and shortkeys from rdebug-core. Break out + filter + test from regular-expression tests. Add chomp test. + +2008-02-16 21:03 Anders Lindgren + + * emacs/rdebug-core.el: The error buffer should work correctly + again (untested) + +2008-02-16 20:56 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-info.el, + emacs/test/test-regexp.el: Moved handling of command output out + from gud-rdebug-marker-filter. It + is now handled by rdebug-cmd-XXX (which used to be located in + rdebug-info.el.) Tooltip handling is now more robust, e.g. it + works + when more than one annotation is received at once, or if the + annotation arrives in split packages. + + In case the external process echoes the command, it is stipped + away + before it is presented as a tooltip. + + Test of filter function reworked. New cases added to handle + command + output. All filter tests are now tested twice, once when the + entire + block is sent at once, one where the block is sent in character + by + character. + +2008-02-16 17:38 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-cmd.el, emacs/rdebug-core.el, + emacs/test/test-indent.el: Add routine to go to a particular + history location. Break out command buffer + things into its own file. + +2008-02-16 13:47 Rocky Bernstein + + * emacs/rdebug-core.el: Show ring number when moving positions. + +2008-02-16 04:18 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-source.el, + emacs/rdebug-vars.el, emacs/rdebug.el: Save stopping points and + give a way to move around in them. + +2008-02-13 21:47 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/processor.rb, lib/ChangeLog: + processor.rb: spelled "post-mortem" incorrectly in prompt. + +2008-02-13 17:58 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-regexp.el, + emacs/rdebug-track.el: Use rdebug-input-prompt-regexp rather than + duplicate strings. Set comint-next/previous-prompt + +2008-02-13 17:32 Rocky Bernstein + + * ChangeLog, emacs/rdebug-core.el, lib/ChangeLog: Set up keys for + comint-next-prompt and comint-previous-prompt. + +2008-02-13 13:08 Rocky Bernstein + + * Rakefile: Newer rubygems depricates Gem::Platform::WIN32 + +2008-02-13 03:47 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-gud.el, emacs/rdebug-vars.el: + Add ability to show print output as a tooltip. This is more a + proof-of-concept than a finished product. + +2008-02-12 05:34 Anders Lindgren + + * emacs/rdebug-core.el: Better documentation for + rdebug-non-annotated-text-kind. + +2008-02-12 02:06 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/info.rb, doc/ruby-debug.texi, + lib/ChangeLog, test/data/info-thread.right, test/thread1.rb: Fix + bug in "info thread verbose" which wasn't showing full traceback. + +2008-02-11 02:29 Rocky Bernstein + + * cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/threads.rb, doc/ruby-debug.texi, + test/data/ctrl.right, test/data/info-thread.cmd, + test/data/info-thread.right, test/data/info.right, + test/test-info-thread.rb: Add "info thread". Pound on "info + threads" to make it more like + pydb. In particular we can give stack traces for the threads. + Towards + addressing issue #12663. + +2008-02-10 20:46 Rocky Bernstein + + * emacs/rdebug-info.el, emacs/rdebug-source.el: Add key to get to + Info buffer. Add "pl" to list of print commands. + +2008-02-10 17:46 Rocky Bernstein + + * Rakefile, emacs/Makefile.am, emacs/rdebug-core.el: Makefile.am, + rdebug-core.el: require/add rdebug-info.el + Rakefile: some indentation + +2008-02-10 16:06 Anders Lindgren + + * emacs/rdebug-info.el: Got rid of warning. (Had to disabled it the + hard way since rdebug-info calls a function in rdebug-core, but + can't require it because that would lead to cyclic requires.) + +2008-02-10 16:01 Anders Lindgren + + * emacs/rdebug-breaks.el, emacs/rdebug-core.el, + emacs/rdebug-info.el, emacs/rdebug-layouts.el, + emacs/rdebug-output.el, emacs/rdebug-vars.el, + emacs/test/test-indent.el: New secondary window 'info', which + displays output of events and + certain commands. The non-annotated-text system reworked to + handle + this. This should be seen as a proof of concept that we can pick + up + the output of, say, "pp". The end result could very well differ + quite + a lot from what we have now. + + New variable 'rdebug-accumulative-buffer', true for buffers that + grow. + Currently "output" and "info". + +2008-02-10 01:39 Rocky Bernstein + + * emacs/rdebug-gud.el, emacs/rdebug-source.el, + emacs/rdebug-varbuf.el: Add more variations of print commands: + pl, ps, pp, and p. + +2008-02-09 22:20 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-layouts.el, + emacs/rdebug-source.el, emacs/rdebug.el: * New window layout "no + shell". This is the "standard" layout with the + "watch" window instead of the "debugger shell" window. + + * Fixed a problem where the Watch window was not initialized + properly + until the first annotation arrived. + + * Fixed a problem where we created far too many buffers, e.g + *rdebug-stopping-test.rb* and *rdebug--test.rb*. + +2008-02-09 16:24 Anders Lindgren + + * emacs/rdebug-frames.el, emacs/rdebug-layouts.el, + emacs/test/test-indent.el: Indentation fixes, plus adding all + rdebug-xxx.el files to the list of files to check. + +2008-02-09 15:48 Rocky Bernstein + + * ChangeLog, lib/ChangeLog, test/data/break-bad.cmd, + test/data/break-bad.right, test/data/break_bad.cmd, + test/data/break_bad.right, test/data/emacs-basic.cmd, + test/data/emacs-basic.right, test/data/emacs_basic.cmd, + test/data/emacs_basic.right, test/helper.rb, + test/test-break-bad.rb, test/test-emacs-basic.rb: helper.rb + Failed attempt to DRY tests more. But save what we have + which may someday in the future be used to go further. Minus to + undercore in Data file names in preparation such time. (We'll use + the + filename as the test name). + + testing + +2008-02-09 11:55 Rocky Bernstein + + * ext/ruby_debug.c, test/data/post-mortem-next.cmd, + test/data/post-mortem-next.right, test/data/post-mortem.cmd, + test/data/post-mortem.right, test/test-pm.rb: Fix bug where we + entered debugger code if we "next" over code that + goes raises an uncaught exception. Needed to reset stepping + parameters. Added a routine to do so. + +2008-02-08 02:09 Rocky Bernstein + + * INSTALL.SVN: Add instructions for building on MS Windows. + +2008-02-06 18:15 Rocky Bernstein + + * emacs/rdebug-breaks.el, emacs/rdebug-core.el, + emacs/rdebug-gud.el, emacs/rdebug-source.el, + emacs/rdebug-varbuf.el: Add routines to print a marked expression + or a variable in the + variables buffer. Not perfect but it's a start in the right + direction. + Add key bindings for this and to print a region selected via the + mouse. + +2008-02-06 16:15 Rocky Bernstein + + * ChangeLog, emacs/Makefile.am, emacs/rdebug-gud.el, + emacs/test/test-gud.el, lib/ChangeLog: Add 'nowarn to + find-file-noselect and test that we don't get a warning. + +2008-02-05 16:30 Rocky Bernstein + + * cli/ruby-debug/interface.rb: Remove "* used as prefix argument" + warning. + +2008-02-05 07:52 Anders Lindgren + + * emacs/rdebug-layouts.el, emacs/rdebug-source.el: Added 'Separate + I/O buffer' to options menu. The window layouts now create an + output buffer only when separate io buffer is enabled. + +2008-02-05 01:41 Rocky Bernstein + + * ChangeLog, emacs/rdebug-track.el, emacs/rdebug.el, lib/ChangeLog, + test/data/setshow.cmd, test/data/setshow.right: rdebug.el: Add a + defgroup for rdebug so customization in Emacs 23 is possible. + Some other minor doc fixes. + setshow.* make sure we don't have an $Id line that we have to + check against. + +2008-02-04 21:50 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug.el: New variable + 'rdebug-use-separate-io-buffer' controls if output should go to + shell window or the output window. Contiuous output can now be + received from a running process. 'gud-rdebug-marker-filter' + totally reworked (again) -- introduced the concept of one-liners + and a new helper function. + +2008-02-03 20:26 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-regexp.el: Annotation filter + reworked. comint-process-echoes is now set, so that the user + commands aren't printed twice. 'quit' now works correcty, and the + stack frame window shows the correct content when post-mortem is + entered. + +2008-02-03 15:23 Rocky Bernstein + + * ChangeLog, Rakefile, doc/ruby-debug.texi, lib/ChangeLog, + test/annotate.cmd, test/annotate.right, test/break-bad.cmd, + test/break-bad.right, test/breakpoints.cmd, + test/breakpoints.right, test/condition.cmd, test/condition.right, + test/ctrl.cmd, test/ctrl.right, test/data, + test/data/annotate.cmd, test/data/annotate.right, + test/data/break-bad.cmd, test/data/break-bad.right, + test/data/breakpoints.cmd, test/data/breakpoints.right, + test/data/condition.cmd, test/data/condition.right, + test/data/ctrl.cmd, test/data/ctrl.right, test/data/display.cmd, + test/data/display.right, test/data/dollar-0.right, + test/data/dollar-0a.right, test/data/dollar-0b.right, + test/data/edit.cmd, test/data/edit.right, + test/data/emacs-basic.cmd, test/data/emacs-basic.right, + test/data/enable.cmd, test/data/enable.right, + test/data/frame.cmd, test/data/frame.right, test/data/help.cmd, + test/data/help.right, test/data/history.right, + test/data/info-var-bug2.cmd, test/data/info-var-bug2.right, + test/data/info-var.cmd, test/data/info-var.right, + test/data/info.cmd, test/data/info.right, test/data/noquit.right, + test/data/output.cmd, test/data/output.right, + test/data/post-mortem.cmd, test/data/post-mortem.right, + test/data/quit.cmd, test/data/quit.right, test/data/raise.cmd, + test/data/raise.right, test/data/setshow.cmd, + test/data/setshow.right, test/data/source.cmd, + test/data/source.right, test/data/stepping.cmd, + test/data/stepping.right, test/data/test-init.right, + test/display.cmd, test/display.right, test/dollar-0.right, + test/dollar-0a.right, test/dollar-0b.right, test/edit.cmd, + test/edit.right, test/emacs-basic.cmd, test/emacs-basic.right, + test/enable.cmd, test/enable.right, test/frame.cmd, + test/frame.right, test/help.cmd, test/help.right, test/helper.rb, + test/history.right, test/info-var-bug2.cmd, + test/info-var-bug2.right, test/info-var.cmd, test/info-var.right, + test/info.cmd, test/info.right, test/noquit.right, + test/output.cmd, test/output.right, test/post-mortem.cmd, + test/post-mortem.right, test/quit.cmd, test/quit.right, + test/raise.cmd, test/raise.right, test/setshow.cmd, + test/setshow.right, test/source.cmd, test/source.right, + test/stepping.cmd, test/stepping.right, test/test-annotate.rb, + test/test-break-bad.rb, test/test-breakpoints.rb, + test/test-condition.rb, test/test-ctrl.rb, test/test-display.rb, + test/test-dollar-0.rb, test/test-edit.rb, + test/test-emacs-basic.rb, test/test-enable.rb, + test/test-frame.rb, test/test-help.rb, test/test-hist.rb, + test/test-info-var.rb, test/test-info.rb, test/test-init.rb, + test/test-init.right, test/test-output.rb, test/test-pm.rb, + test/test-quit.rb, test/test-raise.rb, test/test-setshow.rb, + test/test-source.rb, test/test-stepping.rb: Try to get testing a + little more organized, although more work should + be done: Create a data directory for comparison ("right") and + script + command ("cmd") files. Code is now more uniform (and should DRY'd + a + bit more). + +2008-02-03 12:34 Rocky Bernstein + + * doc/ruby-debug.texi: Remove Debugger.init. Expand Debugger.start, + Debugger.stop and Debugger.started? + +2008-02-03 04:17 Rocky Bernstein + + * cli/ruby-debug/commands/catchpoint.rb, + cli/ruby-debug/commands/info.rb, test/raise.cmd, + test/raise.right: Add some argument checking in setting + catchpoints. + Showing status on "info catch" is a little silly - we can't + recover from + an exception. + +2008-02-02 23:10 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/catchpoint.rb, + cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/edit.rb, cli/ruby-debug/commands/eval.rb, + cli/ruby-debug/commands/help.rb, cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/list.rb, cli/ruby-debug/commands/save.rb, + cli/ruby-debug/commands/script.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, + cli/ruby-debug/commands/stepping.rb, + cli/ruby-debug/commands/threads.rb, cli/ruby-debug/processor.rb, + lib/ChangeLog, test/breakpoints.right, test/emacs-basic.right, + test/pm.rb, test/post-mortem.cmd, test/post-mortem.right, + test/test-emacs-basic.rb, test/test-init.rb, test/test-pm.rb, + test/test-quit.rb: Remove commands in post-mortem which are not + applicable, e.g."step", + "next", "continue"... + + "No breakpoints have been set" is now an error message when + trying to + set a breakpoint. + + Add post-mortem test. + + Debug.init no longer exists. + +2008-02-02 18:16 Anders Lindgren + + * emacs/rdebug-core.el: Changing window layout no longer clears the + secondary windows. + +2008-02-02 16:14 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-source.el: All window layout + menu items are not collected in one place. Comment fixes. + +2008-02-02 09:27 Rocky Bernstein + + * CHANGES, ext/ruby_debug.c, lib/ruby-debug-base.rb, + test/gcd-dbg.rb: Remove Debugger.init and fold options parameter + into Debugger.start. + Old Debugger.start has been renamed Deebugger.start_ + +2008-02-01 03:09 Rocky Bernstein + + * CHANGES, Rakefile, bin/rdebug, + cli/ruby-debug/commands/catchpoint.rb, + cli/ruby-debug/commands/info.rb, cli/ruby-debug/processor.rb, + ext/breakpoint.c, ext/ruby_debug.c, ext/ruby_debug.h, + test/base/base.rb, test/base/catchpoint.rb, test/ctrl.right, + test/info.right: Allow multiple exceptions to be caught. + + INCOMPATIBLE CHANGE: varible Debugger.catchpoint a String was + turned + into Debugger.catchpoints, a Hash. Debugger.catchpoint= no longer + exists. Debugger.set_catchpoint was turned into + Debugger.add_catchpoint + + "info catch" added. + + INCOMPATIBLE CHANGE: variable Debugger.catchpoint is now + Debugger.catchpoints + which is a now hash rather than a String. Debugger.catchpoint= no + longer exists. + + A catchpoint ruby-debug-base test added. use unshift in requires. + + rdebug: --post-mortem now really catches uncaught exceptions and + brings you to post-mortem handling. + +2008-01-31 18:29 Anders Lindgren + + * emacs/rdebug-breaks.el, emacs/rdebug-frames.el: In the frames and + breakpoint windows, the left mouse button simply sets the point. + Double-clicking selects the item. The second and third mouse + button also selects. + +2008-01-31 16:30 Rocky Bernstein + + * ChangeLog, ext/ruby_debug.c, lib/ChangeLog: Leave ruby_debug.c + this way for now. + +2008-01-31 16:24 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/processor.rb, ext/ruby_debug.c, + lib/ChangeLog, test/raise.right, test/tdebug.rb: ruby_debug.c: + more adventures in exception handling + processor.rb: Removal of crash when annotate is on. Need to fix + the source of the + problem though. + +2008-01-31 15:16 Rocky Bernstein + + * bin/rdebug, lib/ruby-debug-base.rb, test/output.right, + test/quit.right, test/raise.rb, test/raise.right, test/tdebug.rb: + Handle post-mortem and exception traceback reporting in + ruby-debug + +2008-01-31 03:01 Rocky Bernstein + + * bin/rdebug, ext/ruby_debug.c, test/helper.rb, test/quit.right, + test/tdebug.rb, test/test-quit.rb, test/test-raise.rb: Have + Debug.load recover from uncaught error raised in a debugged + program. + Go over regression tests. + +2008-01-30 21:33 Anders Lindgren + + * test/raise.cmd, test/raise.rb, test/raise.right, + test/test-raise.rb: Test case ensuring that an error in the user + code doesn't cause the debugger to single step it's own code. + (This is currently broken.) + +2008-01-30 17:13 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb: Add broken "info file" + information. + +2008-01-30 17:01 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/enable.rb, + cli/ruby-debug/commands/info.rb, cli/ruby-debug/commands/show.rb, + lib/ChangeLog, test/condition.right: Add Command.find() to find a + subcommand name. + condition.right: correct for breakpoint hit counts. + +2008-01-30 11:33 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-output.el, + emacs/rdebug-track.el: Add keybindings in shell, output and + command buffers for going to a + traceback line or a $! traceback line. + + rdebug-common-initialization -> rdebug-command-initialization and + fix + up docstring. + + rdebug-core.el: Bug in handling --emacs introduced when a + parameter was added + rdebug-track.el: start with annotate 2. + +2008-01-30 01:43 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/info.rb, lib/ChangeLog, + test/breakpoints.right, test/emacs-basic.right: Add number of + times a breakpoint is hit like gdb does. + +2008-01-29 22:37 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/info.rb, lib/ChangeLog: + Columnize breakpoint output. + +2008-01-29 22:19 Rocky Bernstein + + * cli/ruby-debug/interface.rb, emacs/rdebug-frames.el, + test/test-ctrl.rb: test-ctrl.rb: try to make it influenced less + by environment. + rdebug-frames.el remove unused local variable. + +2008-01-29 21:13 Anders Lindgren + + * cli/ruby-debug/commands/frame.rb, emacs/rdebug-frames.el, + emacs/rdebug-secondary.el: * Fixed a problem where the source + buffer opened in the wrong window. + Turned out that the Stack Frame buffer setup function tried to + display the current frame itself, instead of letting the normal + source annotations handle this. + + * Fixed a problem with an annotation turning up in the debugger + shell + buffer. The 'frame' command emitted a source annotation without + the + "source" part. + + * In the stack frame window, when selecting a frame to display, + the + point is now placed at the beginning of the line of the active + frame. + + * Internal restructuring of the pick source window parts. + +2008-01-29 19:58 Rocky Bernstein + + * emacs/rdebug-frames.el: In the frame secondary buffer, put point + somewhere on the line with + the active frame. (It had been at the end of the buffer.) + +2008-01-29 19:16 Rocky Bernstein + + * emacs/rdebug-layouts.el: So for a layout with one less window and + the command buffer on the bottom. + +2008-01-29 11:20 Rocky Bernstein + + * CHANGES, ChangeLog, bin/rdebug, cli/ruby-debug/interface.rb, + cli/ruby-debug/processor.rb, doc/ruby-debug.texi, + emacs/rdebug-core.el, emacs/rdebug-layouts.el, + emacs/rdebug-source.el, emacs/rdebug.el, emacs/test/test-core.el, + lib/ChangeLog: More annotate=2 fixes. + +2008-01-29 05:03 Anders Lindgren + + * emacs/rdebug-core.el: In Emacs, the current directory of the + debugger shell process is now the directory in which it was + started. + +2008-01-28 21:11 Rocky Bernstein + + * test/history.right, test/test-hist.rb: Disable for now. + +2008-01-28 16:18 Rocky Bernstein + + * test/helper.rb, test/test-hist.rb: Some more work on test-hist. + Not working yet completely though. + +2008-01-28 15:59 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/info.rb, lib/ChangeLog, + test/helper.rb, test/test-dollar-0.rb, test/test-hist.rb, + test/test-output.rb: Add info file breakpoints to show lines + which we can set a breakpoint on. + Revise so we chdir into SRC_DIR. + test-hist.rb is broken - will fix later. + +2008-01-28 15:50 Rocky Bernstein + + * test/history.right: Comparison file for test-hist.rb + +2008-01-28 03:16 Rocky Bernstein + + * doc/Makefile.am: Don't remove Unix manual page. + +2008-01-28 03:15 Rocky Bernstein + + * cli/ruby-debug/commands/show.rb, doc/ruby-debug.texi: Make show + commands a little more like gdb. Document it too. + +2008-01-28 02:24 Rocky Bernstein + + * cli/ruby-debug/commands/show.rb, cli/ruby-debug/interface.rb, + test/ctrl.right, test/test-enable.rb, test/test-hist.rb: + interface.rb: Command history not saved between local rdebug + sessions. Patch from Martin Krauskopf #17491. + show.rb: add "show commands" so we can see the command history. + test/* Add a history regression test. + +2008-01-26 17:12 Anders Lindgren + + * emacs/rdebug-frames.el: debug--setup-frame-buffer rewritten from + scratch, it's now a lot simpler since it no longer has to handle + coloring. + +2008-01-26 17:10 Anders Lindgren + + * emacs/rdebug-layouts.el: comment fix. + +2008-01-26 16:33 Anders Lindgren + + * emacs/rdebug-breaks.el, emacs/rdebug-frames.el: Coloring added to + the Stack frames window + +2008-01-26 01:45 Rocky Bernstein + + * test/test-annotate.rb, test/test-enable.rb, test/test-init.rb, + test/test-init.right: Add test of new Debugger.init + +2008-01-25 21:02 Rocky Bernstein + + * doc/ruby-debug.texi: Document info subcommands and Debugger.init. + Start Class, Module, + method index. Order of index changed slightly. + +2008-01-25 12:11 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, lib/ChangeLog, + lib/ruby-debug-base.rb, test/gcd-dbg-nox.rb, test/gcd-dbg.rb: Add + Debugger.init which intializes things that rdebug does. This + allows a restart even though rdebug wasn't called initially. + +2008-01-23 02:53 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/enable.rb, + cli/ruby-debug/commands/help.rb, cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, test/breakpoints.cmd, + test/breakpoints.right, test/enable.cmd, test/enable.right, + test/help.cmd, test/help.right, test/test-enable.rb, + test/test-help.rb: Add subcommand/long help for enable, disable, + set, and show. Put Subcommand structure in Command. More work is + needed to reduce redundancy. + +2008-01-22 23:15 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/help.rb, + cli/ruby-debug/commands/info.rb, lib/ChangeLog, + test/annotate.cmd, test/annotate.right, test/ctrl.right, + test/info.cmd, test/info.right, test/test-edit.rb, + test/test-source.rb: Allow "help info xxx". Add ability for long + help on "info" command. + Add "info break xx". + + test: remove test/unit class name conflicts. All the tests we + wrote + now get run. + +2008-01-22 18:48 Rocky Bernstein + + * emacs/rdebug-secondary.el: A small comment spelling mistake. + +2008-01-20 22:01 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb, test/break-bad.cmd, + test/break-bad.right, test/breakpoints.cmd, + test/breakpoints.right, test/rdebug-save.1, test/source.right, + test/test-break-bad.rb: We now only allow breakpoints on stopping + lines. We get this via + linecache which ultimately gets it from ParseTree. + +2008-01-19 19:28 Rocky Bernstein + + * ChangeLog, Rakefile, lib/ChangeLog, test/base, test/base/base.rb, + test/base/binding.rb, test/test-ruby-debug-base.rb: Move + ruby-debug-base tests to base directory. Add a binding_n + regression test. + +2008-01-17 22:29 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb: lines -> size. + +2008-01-17 20:28 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb, test/ctrl.right, + test/info.right: Add "info file" in addition to "info files" Use + some features in linecache 0.3 + which are in SVN only. Give SHA1, number of lines and timestamp + on a specific + file. + +2008-01-17 06:58 Rocky Bernstein + + * test/ctrl.right: info file -> info files + +2008-01-17 03:33 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb, test/info.right: "info file" -> + "info files" as per gdb. + +2008-01-16 18:42 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/breakpoints.rb, lib/ChangeLog, + test/annotate.right, test/breakpoints.right, + test/condition.right, test/display.right, test/emacs-basic.right, + test/info-var.right: Need to present source filename (__FILE__) + as Ruby and therefore breakpoint + sees it. + + +2008-01-16 12:30 Rocky Bernstein + + * emacs/rdebug-track.el: Slightly better rdebug-track-attach + initialization. Still has problems, but it's better. + +2008-01-16 02:19 Rocky Bernstein + + * ChangeLog, Rakefile, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/list.rb, lib/ChangeLog, + lib/ruby-debug-base.rb: Line caching moved to an external gem, + linecache. We now require + version 0.2 of that or greater. + +2008-01-16 01:14 Rocky Bernstein + + * emacs/rdebug-source.el: Get insert working again. + +2008-01-16 01:13 Rocky Bernstein + + * emacs/rdebug-secondary.el: Typo. + +2008-01-16 00:23 Rocky Bernstein + + * emacs/rdebug-core.el: Chomp error before message'ing. + +2008-01-15 23:41 Anders Lindgren + + * emacs/rdebug-core.el: When starting 'rdebug' the first time, the + file name of the current buffer is suggested as script name. + +2008-01-15 23:34 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-source.el: Local short key + mode renamed to internal short key mode. Original read-only + status saved in local variable. Minor mode text 'ShortKey' added. + +2008-01-15 23:04 Anders Lindgren + + * emacs/rdebug-breaks.el, emacs/rdebug-core.el, + emacs/rdebug-dbg.el, emacs/rdebug-error.el, + emacs/rdebug-frames.el, emacs/rdebug-gud.el, + emacs/rdebug-help.el, emacs/rdebug-layouts.el, + emacs/rdebug-output.el, emacs/rdebug-regexp.el, + emacs/rdebug-secondary.el, emacs/rdebug-source.el, + emacs/rdebug-track.el, emacs/rdebug-varbuf.el, + emacs/rdebug-vars.el, emacs/rdebug-watch.el, emacs/rdebug.el: + Comment fixes. + +2008-01-15 22:48 Anders Lindgren + + * emacs/rdebug-breaks.el: Breakpoints font-lock rules even more + generous, now all characters are matched. + +2008-01-15 22:44 Anders Lindgren + + * emacs/rdebug-core.el: rdebug-get-script-name now skips ruby + options, if present + +2008-01-15 07:56 Rocky Bernstein + + * emacs/rdebug-breaks.el: File names can have a - in them. + +2008-01-15 06:51 Anders Lindgren + + * emacs/rdebug-breaks.el, emacs/rdebug-core.el: The source + breakpoint toggle and toggle enabled commands, when issued in the + breakpoints window, do the right thing. In other non-file buffers + they do nothing. + +2008-01-15 04:57 Rocky Bernstein + + * emacs/test/test-core.el: indentation. + +2008-01-15 04:56 Rocky Bernstein + + * emacs/test/test-core.el: More tests. + +2008-01-14 22:22 Anders Lindgren + + * emacs/rdebug-breaks.el: Replaced code coloring breakpoint buffer + with font-lock rules. Now coloring of breakpoints of kind + 'Type:function' works. + +2008-01-14 07:00 Anders Lindgren + + * emacs/rdebug-core.el, emacs/test/test-core.el: + rdebug-get-script-name now handles something else than 'rdebug' + as command name. Rewritten to get rid of unmaintanable recursive + function. + +2008-01-14 06:58 Anders Lindgren + + * emacs/test/test-cmd.el: Breakpoints are now parsed and cached + when a new annotation arrives. + +2008-01-14 06:57 Anders Lindgren + + * emacs/rdebug-breaks.el: Breakpoints are now parsed and cached + when a new annotation arrives. + +2008-01-14 01:31 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/control.rb, + emacs/rdebug-core.el, emacs/rdebug-track.el, lib/ChangeLog: Make + rdebug-track work better in the face of prompt and error + annotations. + control.rb: need another test when rdebug not called initially. + +2008-01-13 22:03 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-layouts.el: A couple more + stack -> frame spots missed + +2008-01-13 21:51 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/breakpoints.rb, + emacs/rdebug-core.el, emacs/rdebug-frames.el, + emacs/rdebug-source.el, ext/breakpoint.c, lib/ChangeLog: Some + stack -> frame renaming + ext/breakpoint.c: put methods in alpha order (to help with + reference man) + breakpoints.rb: one print -> errmsg + +2008-01-13 21:19 Rocky Bernstein + + * doc/ruby-debug.texi: Add info about the 3 kinds of interfaces and + give some + Debugger::Breakpoint methods. + +2008-01-13 20:32 Rocky Bernstein + + * test/test-output.rb: Seems we don't get a core dump any more. + +2008-01-13 18:13 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/condition.rb, + cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/edit.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/help.rb, cli/ruby-debug/commands/info.rb, + cli/ruby-debug/interface.rb, cli/ruby-debug/processor.rb, + emacs/Makefile.am, emacs/rdebug-core.el, emacs/rdebug-error.el, + emacs/rdebug-output.el, emacs/rdebug-source.el, lib/ChangeLog, + test/annotate.cmd, test/annotate.right, test/breakpoints.right, + test/condition.right, test/edit.right, test/emacs-basic.right, + test/frame.right: Create errmsg routine for error output, start + tagging error messages + as errors. Under annotate 3, output errors similar to gdb + --annotate + does (although still simplified). Have Emacs pick up debugger + error + annotations. + +2008-01-13 04:05 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/enable.rb, cli/ruby-debug/helper.rb, + cli/ruby-debug/interface.rb, cli/ruby-debug/processor.rb, + lib/ChangeLog, test/condition.cmd, test/condition.right: Check + validity of expressions in breakpoint conditions and don't allow + enabling a syntactically invalid expression. + + Start noting messages which are errors via an errmsg routine. + +2008-01-12 13:35 Rocky Bernstein + + * CHANGES: Typo. + +2008-01-12 13:22 Rocky Bernstein + + * emacs/rdebug-core.el: Typo. + +2008-01-12 12:45 Rocky Bernstein + + * emacs/rdebug-breaks.el, emacs/rdebug-frames.el: breaks.el + gdb-put-breakpoint-icon seems to want to string for a breakpoint + number and our entries are + numbers. + frames.el: wasn't resetting search string to first line pattern + (for subsequent testing of + whether this is the current frame) after processing split entry + with file/line position. Break out + a common routine rdebug-stack-buffer-field which also seems to + simplify it. + +2008-01-12 10:56 Anders Lindgren + + * emacs/rdebug-breaks.el: Breakpoint icons are now displayed in the + margin. This is a simple implementation that used gdb-ui to do + the actual display. + +2008-01-11 18:04 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-frames.el, + emacs/rdebug-regexp.el, emacs/test/test-frames.el: Process frames + which are split across two lines. DRY a little + and add the first frame test. + +2008-01-11 15:08 Rocky Bernstein + + * emacs/Makefile.am: ELC typo. + +2008-01-11 14:01 Rocky Bernstein + + * emacs/Makefile.am: Don't give an error on "make test" if emacs is + not around. + +2008-01-11 10:26 Rocky Bernstein + + * ChangeLog, bin/rdebug, doc/ruby-debug.texi, lib/ChangeLog: + Document that ruby-debug resets $0. Align program options in ref + manual and --help. Alphabetize better. + +2008-01-11 10:10 Rocky Bernstein + + * CHANGES, bin/rdebug, test/output.right, test/quit.right, + test/tdebug.rb, test/test-quit.rb: rdebug: do syntax checking + when running as server as well as local interface. --no-quit + intercepts Syntax Errors now + (which shouldn't happen and means there's another bug in there to + fix; but robustness is good.) + Bring tdebug.rb more in line iwth rdebug until we can get rid of + it altogether. Note some of the current weaknesses. + +2008-01-10 22:56 Rocky Bernstein + + * ChangeLog, bin/rdebug, lib/ChangeLog, test/dollar-0.rb, + test/dollar-0.right, test/dollar-0a.right, test/dollar-0b.right, + test/test-dollar-0.rb: More correct $0 fix. Deal with the case ./ + is automatically added. + However this might not be right in all cases. + +2008-01-10 22:25 Rocky Bernstein + + * ChangeLog, emacs/rdebug-core.el, emacs/test/test-core.el, + lib/ChangeLog: Was gobbling arg in processing --emacs. Add test. + +2008-01-10 21:57 Rocky Bernstein + + * bin/rdebug, emacs/rdebug-core.el, test/dollar-0.rb, + test/dollar-0.right, test/helper.rb, test/test-dollar-0.rb: Fix + for "if $0 == __FILE__" idiom. Bug #16038 + rdebug-core.el add '--'; -emacs -> --emacs + rdebug: add subroutines for calling debugger and processing + options. + +2008-01-10 10:34 Rocky Bernstein + + * CHANGES, ChangeLog, cli/ruby-debug/commands/condition.rb, + cli/ruby-debug/commands/enable.rb, cli/ruby-debug/processor.rb, + doc/ruby-debug.texi, emacs/Makefile.am, emacs/rdebug-breaks.el, + emacs/rdebug-regexp.el, emacs/test/test-regexp.el, + ext/breakpoint.c, lib/ChangeLog, test/condition.cmd, + test/condition.right, test/test-breakpoints.rb, + test/test-condition.rb: Add condition command. + +2008-01-10 09:07 Rocky Bernstein + + * emacs/rdebug-frames.el, emacs/rdebug-regexp.el, + emacs/test/test-cmd.el: rdebug-frames.el: fix redisplay of source + when frames change by running rdebug-display-line in creating + frame buffer. require things we need to require to eval this + file. set-local-variables. + + rdebug-regexp.el: add constants for file and line stack positions + in regexp. + + test-cmd.el: rdebug-cmd -> rdebug-gud. + +2008-01-09 23:00 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-gud.el, + emacs/test/test-indent.el: Some more GUD things moved to gud-el. + +2008-01-09 22:56 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-breaks.el, emacs/rdebug-cmd.el, + emacs/rdebug-core.el, emacs/rdebug-gud.el, + emacs/rdebug-regexp.el: rdebug-cmd.el -> rdebug-gud.el + Move gud things from rdebug-core.el to rdebug-gud.el + +2008-01-09 22:37 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-source.el: Allow [insert] to + turn on/off short-key-mode. + +2008-01-09 19:10 Rocky Bernstein + + * ChangeLog, Rakefile, emacs/rdebug-dbg.el, lib/ChangeLog: + Rakefile: rdebug.rb -> rdbg.el + rdebug-dbg.el: Add $Id$ + +2008-01-09 19:03 Rocky Bernstein + + * ChangeLog, emacs/Makefile.am, emacs/rdebug-breaks.el, + emacs/rdebug-cmd.el, emacs/rdebug-core.el, emacs/rdebug-dbg.el, + emacs/rdebug-frames.el, emacs/rdebug-help.el, + emacs/rdebug-output.el, emacs/rdebug-secondary.el, + emacs/rdebug-track.el, emacs/rdebug-varbuf.el, + emacs/rdebug-watch.el, emacs/test/test-indent.el, + emacs/test/test-regexp.el, lib/ChangeLog: Break out secondary + buffer into their own file, and also internal + debug code and general secondary commands. Secondary buffer code + removed from rdebug-cmd and moved into the appropriate file. + + rdebug-edit-variables-value is not defined so comment out for + now. + +2008-01-08 16:11 Rocky Bernstein + + * emacs/rdebug-core.el: Change indentation. + +2008-01-08 16:04 Rocky Bernstein + + * ChangeLog, lib/ChangeLog, rdbg.rb: Restore $: to the value it was + before rdebug call. + +2008-01-08 12:04 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-core.el, emacs/rdebug-layouts.el, + emacs/rdebug-vars.el: rdebug-layouts.rb, Makefile.am: window + layouts - split off from rdebug-core.el + Add some output commands: command to add a marker line, clear the + output window, and allow undo. + +2008-01-08 06:30 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-source.el: New and old + byte-compile warnings eliminated. + +2008-01-08 02:36 Rocky Bernstein + + * INSTALL.SVN, Rakefile, rdbg.rb, test/helper.rb, + test/test-breakpoints.rb, test/test-output.rb, test/test-quit.rb: + Rewrite runner.sh in Ruby: rdbg.rb + Were it not for a bug that needs to be fixed, we could + remove runner.sh. test-output.rb hits this bug. + +2008-01-07 23:02 Rocky Bernstein + + * README: Note need for VC6. + +2008-01-07 20:51 Rocky Bernstein + + * CHANGES: What's changed. + +2008-01-07 20:38 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/variables.rb, lib/ChangeLog: Add "var + class". This means "var const .." can no longer be abbreviated + "var c"; use "var co" instead. + (Or "var const" or "var constant" + +2008-01-07 19:57 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/info.rb, lib/ChangeLog, + test/info-var-bug.rb, test/info-var.cmd, test/info-var.right: Add + class level variables to "info variables" + +2008-01-07 17:37 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/info.rb, lib/ChangeLog, + test/annotate.right, test/info-var-bug2.right, + test/info-var.right, test/output.right, test/test-info-var.rb: + Add "self" to list "info variables" spits out. + +2008-01-07 10:36 Rocky Bernstein + + * emacs/Makefile.am: Missing a backslash to continue a line. + +2008-01-07 10:21 Anders Lindgren + + * emacs/rdebug-core.el: Fixed problem with byte-compile warning due + to an extra comma. + +2008-01-07 09:59 Rocky Bernstein + + * ChangeLog, Rakefile, bin/rdebug, emacs/rdebug-core.el, + lib/ChangeLog: --emacs sets width to 120. rdebug-core.el will + reset to 120 unless it's already that. + +2008-01-07 09:08 Rocky Bernstein + + * README: Add Anders' instruction on how to compile in MS Windows + (modified slightly). + +2008-01-07 04:29 Rocky Bernstein + + * ChangeLog, Makefile.am, ext/ChangeLog, lib/ChangeLog: Split out + ChangeLogs better (I hope). + +2008-01-06 21:16 Rocky Bernstein + + * bin/rdebug: Syntax error. + +2008-01-06 20:56 Rocky Bernstein + + * ChangeLog, bin/rdebug, cli/ruby-debug/processor.rb, + emacs/rdebug-core.el, emacs/rdebug-regexp.el, + emacs/test/test-regexp.el, ext/ChangeLog, lib/ChangeLog, + test/emacs-basic.cmd, test/emacs-basic.right, test/quit.right, + test/tdebug.rb, test/test-emacs-basic.rb: test/*-emacs-basic*, + tdebug: Add test of running in Emacs without annotations. + + emacs/*.el: make regexp tests work again, move regexp to from + core to regexp. + Add an annotate regexp test. + + processor.rb: Remove some anotation print from bleeding into + output + when annotations are not wanted. Reinstate "Program finished" in + annotations and outside (rdebug). + +2008-01-06 18:55 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/processor.rb, emacs/Makefile.am, + emacs/rdebug-core.el, emacs/test/test-indent.el, ext/ChangeLog, + lib/ChangeLog, test/annotate.right, test/output.right: Create + Processor class and subclass that. Perhaps a mixin would be good. + Remove annotation output bleanding when annotate is off. + Try to reduce the mess annotations is adding to processor.rb + rdebug-core.el: fix indentation to pass the regression test + Anders added + Makefile.am: Add rdebug-source.el to distribution. + Make sure "rake test" + +2008-01-06 12:31 Anders Lindgren + + * bin/rdebug, cli/ruby-debug/processor.rb, emacs/rdebug-core.el, + emacs/rdebug-regexp.el: Emacs interface adopted to new + annotations scheme. + +2008-01-06 06:46 Rocky Bernstein + + * test/source.right: correct output for source test + +2008-01-06 06:44 Rocky Bernstein + + * cli/ruby-debug/commands/save.rb, + cli/ruby-debug/commands/script.rb, cli/ruby-debug/interface.rb, + cli/ruby-debug/processor.rb, test/rdebug-save.1, test/source.cmd, + test/test-source.rb: The source command now allows us to read in + breakpoint in the current + context. More work is needed but this is a start. + +2008-01-06 02:15 Rocky Bernstein + + * ChangeLog, bin/rdebug, cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/save.rb, + cli/ruby-debug/commands/script.rb, cli/ruby-debug/interface.rb, + cli/ruby-debug/processor.rb, ext/ChangeLog, lib/ChangeLog: Some + work on saving state across a restart. More work is needed on the + script command to get this working. The save-file name is now + optional. save.rb split off from script.rb Display expressions + and + some settings are now captured in the save/restore file. + Add interface.finalize - things that need to be done before quit + or + restart. + +2008-01-05 21:16 Rocky Bernstein + + * ChangeLog, bin/rdebug, cli/ruby-debug/interface.rb, + cli/ruby-debug/processor.rb, ext/ChangeLog, lib/ChangeLog, + test/annotate.right, test/output.cmd, test/output.right, + test/quit.right, test/tdebug.rb, test/test-output.rb: More work + to make annotate more like gdb's. starting/stopping/exiting + should be more similar. Some code has been commented out until we + get + the Emacs interface to match. See "FIXME: ANNOTATE" in + processor.rb. + Also regression tests for output and annotate currently fail for + this + reason. + +2008-01-05 16:32 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-source.el, emacs/rdebug.el, + emacs/test/test-indent.el: rdebug-source.el now spawned off from + rdebug-core.el. + +2008-01-05 15:46 Anders Lindgren + + * emacs/rdebug-source.el: Initial commit of split of + rdebug-code.el. (Currently, rdebug-source.el is straight copy of + rdebug-core.el.) + +2008-01-05 15:05 Anders Lindgren + + * emacs/rdebug-core.el: New commands for displaying to the source + buffer 'rdebug-display-source-buffer' and ...-resync'. The former + is bound to S in the secondary buffers. Added View->Source to the + menu bar. + +2008-01-05 13:46 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/edit.rb, cli/ruby-debug/helper.rb, + doc/ruby-debug.texi, test/ctrl.right, test/edit.cmd, + test/edit.right, test/test-edit.rb: Add edit command. + breakpoints.rb/helper.rb: bad regular-expression separation. + +2008-01-05 13:24 Anders Lindgren + + * test/output.cmd, test/output.rb, test/output.right, + test/test-output.rb: Added test case for the 'starting' + annotation. (It currently fails since the annotation is broken.) + +2008-01-05 10:40 Anders Lindgren + + * emacs/rdebug-core.el: New selection algorithm for picking the + best secondary window, as suggested in rubyforge issue 1950. + +2008-01-05 10:36 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb: Catch places were we + can't set breakpoints or delete breakpoints because + we don't have context set. + +2008-01-04 07:43 Rocky Bernstein + + * cli/ruby-debug/interface.rb: @history_save can sometimes be + undefined. Test for it so we don't get a warning + when $DEBUG/$WARING is true. + +2008-01-03 18:54 Anders Lindgren + + * emacs/rdebug.el: When running 'make' (comp-elisp) an error was + triggered. This is probably a problem in comp-elisp since nil is + part of the initial load-path. A work-around was added in + 'rdebug-compare-directories'. + +2008-01-03 15:44 Rocky Bernstein + + * emacs/rdebug-core.el: Deal with a killed gud-comint-buffer. + +2008-01-03 10:34 Anders Lindgren + + * emacs/rdebug-cmd.el, emacs/rdebug-core.el, + emacs/test/test-indent.el: Indentation: fixed problem with test + case and some real minor indentation issues. + +2008-01-03 10:34 Rocky Bernstein + + * emacs/Makefile.am: Filename typo. + +2008-01-03 07:33 Anders Lindgren + + * emacs/rdebug-cmd.el, emacs/rdebug-core.el, emacs/rdebug.el: The + directory of rdebug.el is added to the load-path. (The trick to + add . doesn't work since it referes to the current directory of + the current user buffer, not the file being loaded.) + +2008-01-03 07:11 Anders Lindgren + + * emacs/rdebug-core.el: Added a Options->Window Layout submenu. It + sets and redisplays the window layout, so that the user can try + out the available window layouts. + +2008-01-02 20:35 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/helper.rb, ext/ChangeLog, lib/ChangeLog: + helper.rb: add regexp for a position. TODO: add parsing routine + and use in + various commands + +2008-01-02 17:39 Anders Lindgren + + * emacs/rdebug-cmd.el, emacs/rdebug-core.el, + emacs/rdebug-regexp.el, emacs/rdebug-track.el, emacs/rdebug.el: + New comment headers added. Minor rearrangement of functions. + +2008-01-02 17:31 Rocky Bernstein + + * test/test-ruby-debug-base.rb: A little more robust. + +2008-01-02 14:41 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/processor.rb, emacs/rdebug.el, + ext/ChangeLog, lib/ChangeLog, test/annotate.right: processor.rb: + Redo where starting/exiting annotations are done. + rdebug.el: back off on setting output command for now. + +2008-01-02 04:17 Rocky Bernstein + + * test/quit.cmd, test/quit.right, test/tdebug.rb, + test/test-quit.rb: --no-quit bug fixed. But we don't know how to + test it properly yet. + +2008-01-02 04:04 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/commands/info.rb, + cli/ruby-debug/processor.rb, cli/ruby-debug/theend.rb, + test/annotate.right, test/ctrl.cmd, test/ctrl.right, + test/test-ctrl.rb, test/test-help.rb, test/test-info.rb: Redo how + --no-quit is handled. We now go into a control state with + limited commands. + + Add annotation for "exiting" + + Add regression test for ctrl debugger state. "info" commands are + allowed this state although most don't do anything. Some tests + comments corrected. + +2008-01-01 15:23 Rocky Bernstein + + * ChangeLog, bin/rdebug, ext/ChangeLog, lib/ChangeLog: Fix --emacs + to do --no-quit properly. + +2008-01-01 09:00 Rocky Bernstein + + * ChangeLog, ext/ChangeLog, ext/breakpoint.c, ext/ruby_debug.c, + ext/ruby_debug.h, lib/ChangeLog: Remove RDoc warnings caused + because C files have been split up. + +2008-01-01 08:18 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug.el: Add + rdebug-user-separate-io-buffer to let folks decide where output + should appear - similar to gdb-ui's + rdebug-user-separate-io-buffer. + Move customizable variables from rdebug-core.el to rdebug.el. + +2008-01-01 05:51 Rocky Bernstein + + * ChangeLog, emacs/Makefile.am, emacs/test/test-indent.el, + emacs/test/test-reindent.el, ext/ChangeLog, lib/ChangeLog: + reindent -> indent. Makefile.am: wasn't including all test files. + +2008-01-01 05:45 Rocky Bernstein + + * emacs/Makefile.am, emacs/elk-test.el, emacs/rdebug-test-cmd.el, + emacs/rdebug-test-regexp.el, emacs/rdebug-test.el, emacs/test, + emacs/test/elk-test.el, emacs/test/test-cmd.el, + emacs/test/test-core.el, emacs/test/test-regexp.el, + emacs/test/test-reindent.el: Create test directory and put + regression tests in that. + +2007-12-31 15:38 Rocky Bernstein + + * configure.ac: Now in 0.10.1 + +2007-12-31 15:37 Rocky Bernstein + + * doc/triangle.rb: Another example program used in documentation. + +2007-12-31 06:26 Rocky Bernstein + + * ChangeLog, Rakefile, ext/ChangeLog, lib/ChangeLog: Rakefile: add + spit-off C files to ruby-debug-base gem. + +2007-12-31 06:23 Rocky Bernstein + + * ChangeLog, emacs/rdebug-test-cmd.el, ext/ChangeLog, + lib/ChangeLog: rdebug-test-cmd.el: Indentation + +2007-12-31 06:20 Rocky Bernstein + + * ext/breakpoint.c: Was missing check_breakpoint_expression(). + +2007-12-31 06:08 Rocky Bernstein + + * CHANGES, ChangeLog, lib/ChangeLog: Changes and more changes. + +2007-12-31 06:06 Rocky Bernstein + + * ext/ChangeLog, ext/breakpoint.c, ext/ruby_debug.c, + ext/ruby_debug.h: Split off breakpoint code from ruby_debug.c; + add common ruby_debug.h + header Alas this means some statics are now externs and one + inline was + dropped. In some cases though moving static to extern might be + desirable for other packages that want to hook into ruby_debug. + Start to preface the global ruby_debug variables with rdebug. + +2007-12-31 05:55 Rocky Bernstein + + * bin/rdebug, doc/rdebug.1, doc/ruby-debug.texi, emacs/Makefile.am, + emacs/rdebug-core.el, emacs/rdebug-test-cmd.el, + emacs/rdebug-test.el, test/runall: rdebug, emacs/* doc/*: --emacs + is now --emacs-basic while --emacs now implies + --emacs-basic --annotate=3 --post-mortem --no-control --no-start + --no-quit + runall: test-*.rb are tests + rdebug-test-cmd.el: use 'require and add tests of + rdebug-{step,next}. + emacs/Makefile.am: break out individual test as separate targets. + +2007-12-30 10:54 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-test-cmd.el, + emacs/rdebug-test-frame.el, emacs/rdebug-vars.el: rdebug-vars.el: + remove cut-and-paste artifact + rest: rdebug-test-frame.el -> rdebug-test-cmd.el + +2007-12-30 10:26 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-cmd.el, emacs/rdebug-core.el, + emacs/rdebug-regexp.el, emacs/rdebug-track.el, + emacs/rdebug-vars.el: Break up rdebug-core.el. Split out + variables, regexps, and debugger commands. + +2007-12-30 10:13 Anders Lindgren + + * emacs/rdebug-core.el: New function + 'rdebug-turn-on-short-key-mode', designed to be used in user + hooks. + +2007-12-30 10:08 Anders Lindgren + + * emacs/rdebug-core.el: C-x C-a C-q now toggles short key mode + +2007-12-29 23:04 Rocky Bernstein + + * doc/ruby-debug.texi: Add subsection as to why no parameter values + in a call stack. + +2007-12-29 22:05 Rocky Bernstein + + * doc/rdebug.1, doc/ruby-debug.texi: Remove short -n option; + --no-stop remains. + +2007-12-29 15:19 Anders Lindgren + + * emacs/rdebug-core.el: Added 'Customize Rdebug' to the Options + submenu. + +2007-12-29 13:31 Rocky Bernstein + + * ChangeLog, bin/rdebug, cli/ruby-debug/command.rb, ext/ChangeLog, + lib/ChangeLog, test/helper.rb, test/noquit.right, test/null.rb, + test/quit.cmd, test/quit.right, test/tdebug.rb: Remove looping on + quit. "-n" is broken so remove it for now. + +2007-12-29 12:27 Rocky Bernstein + + * emacs/rdebug-core.el: -(require 'cl) needed for ignore-errors. + -Short key bindings added: "b" for break "t" for toggle. + -Common key bindings added/changed + R (along with r) is restart. Restart prompts, like quit does. + +, - and _ are now modifiers to step and next; _ takes the + default. + - Numeric argument on "continue" goes to that line, e.g. M-10 + continue is + "continue 10", not "continue" 10 times. + +2007-12-29 10:50 Anders Lindgren + + * bin/rdebug, cli/ruby-debug/theend.rb: * The 'theend.rb' script is + now always loaded with the 'stop' flag. + + * The 'theend.rb' script is now loaded after the restarted print + statement. + + * Removed an 'if' statement preventing restart when the no-stop + flag + was used. + + * Added end-of-line comment in 'theend.rb' on the same line as + the + single statement. This helps people that use the command-line + debugger. + +2007-12-29 09:29 Anders Lindgren + + * bin/rdebug, cli/ruby-debug/theend.rb: When the end of the program + is reached and the --no-quit option is + used, the user now steps into the file 'theend.rb'. This file + contains + a message telling the user that the end of the application has + been + reached. For a normal debug session this feels better. However, + if the + user file is empty, this prevents the debugger from going into an + infinite loop. + + Note, an alternative implementation would be if the debugger + itself + would create an artificial step point at the of the the user + program. + +2007-12-29 08:49 Anders Lindgren + + * emacs/rdebug-core.el: New feature requested by Rocky: Source + short key mode, in the source buffer that corresponds to the + current frame read-only is activated and the plain secondary + buffer keys are bound. + +2007-12-29 00:50 Rocky Bernstein + + * emacs/rdebug-test-frame.el: Remove c: as that's not OS + independent. + +2007-12-28 20:06 Rocky Bernstein + + * doc/ruby-debug.texi: Another misspelling. + +2007-12-28 20:04 Rocky Bernstein + + * doc/ruby-debug.texi: Another typo. + +2007-12-28 20:01 Rocky Bernstein + + * doc/ruby-debug.texi: Tag code/directory sections better. + +2007-12-28 15:33 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/info.rb, cli/ruby-debug/processor.rb, + ext/ChangeLog, lib/ChangeLog, test/annotate.right, + test/display.cmd, test/display.right: info.rb: Incorrect test for + no display expressions. + display.rb: Grammar thing. + processor.rb: Slightly cleaner code + test/* more/better tests. + +2007-12-28 15:04 Rocky Bernstein + + * test/annotate.right, test/info-var-bug2.right: Forgot to check in + these files when adding new tests + +2007-12-28 13:48 Rocky Bernstein + + * cli/ruby-debug/processor.rb, test/annotate.cmd: Reduce + unneccessary display annotation output. + +2007-12-28 11:27 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-test-regexp.el, + emacs/rdebug-test.el: Split off Emacs test which are regular + expression oriented. + +2007-12-28 10:54 Rocky Bernstein + + * test/test-annotate.rb: *** empty log message *** + +2007-12-28 10:54 Rocky Bernstein + + * test/test-annotate.rb: Doc bug. + +2007-12-28 10:53 Rocky Bernstein + + * test/test-annotate.rb: My old cut-and-paste error. Gotta get in + my "method redefined" patch into rake's test/unit. + +2007-12-28 10:47 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/processor.rb, test/annotate.cmd, + test/test-annotate.rb: Reduce unnecesary breakpoint, stack, and + variable post-command annotations. + Fix bug in not showing empty breakpoints when last one is + deleted. + +2007-12-28 10:12 Anders Lindgren + + * emacs/rdebug-test-frame.el, emacs/rdebug-test.el: Test cases for + new source buffer breakpoint commands. + +2007-12-27 23:20 Anders Lindgren + + * emacs/rdebug-core.el: Two new breakpoint commands for source + buffers: toggle break point and toggle enable/disable. (The + commands corresponds to F9 and C-F9 in common debuggers + interfaces.) + +2007-12-27 21:05 Rocky Bernstein + + * emacs/rdebug-track.el: Lacking a quote in the last commit. + +2007-12-27 21:03 Rocky Bernstein + + * ChangeLog, emacs/rdebug-track.el, ext/ChangeLog, lib/ChangeLog: + Be more agressive about resetting gud-last-frame and + gud-last-last-frame. These foul up tracking when debugging is + interrupted. + We probably need a special "reset" command. + +2007-12-27 03:11 Rocky Bernstein + + * Rakefile, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/enable.rb, cli/ruby-debug/helper.rb, + doc/ruby-debug.texi, emacs/rdebug-test-frame.el, + test/test-columnize.rb: Use columnize gem from rubyforge. + Remove toggle since Anders can't use - easy come, easy go. + rdebug-test-frame.el was broken. + +2007-12-26 22:31 Anders Lindgren + + * emacs/rdebug-core.el: Fix for broken 'rdebug-goto-frame-n'. + +2007-12-26 21:20 Rocky Bernstein + + * README: Note we (may) need "sudo" before installing. Also note + the test options. + +2007-12-26 20:29 Rocky Bernstein + + * CHANGES: *** empty log message *** + +2007-12-26 19:10 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-test-frame.el: Add regression + tests for new code. + +2007-12-26 18:42 Rocky Bernstein + + * emacs/rdebug-core.el: Doc fixes. + +2007-12-26 18:35 Rocky Bernstein + + * ChangeLog, ext/ChangeLog, ext/ruby_debug.c, lib/ChangeLog: + Version number games - maybe 0.10.1 is better. + +2007-12-26 18:18 Rocky Bernstein + + * emacs/rdebug-core.el: Number keys should move the frame, not just + position the cursor there. + +2007-12-26 10:41 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb, test/info-var-bug2.cmd, + test/info-var-bug2.rb, test/test-info-var.rb: Need to escape + escape (% -> %%) in "info variables" + +2007-12-26 00:04 Rocky Bernstein + + * ext/ruby_debug.c: 2nd attempt to deal with *both* problems Timur + reported. + + 1. Catchpoint is never called when program raises an object of + type + Exception. So, my exceptional breakpoints doesn't work for + Exception + class. + + + 2. When SystemExit exception is raised debugger become stopped + and + stop method is called as many times, as a number of threads + running in + application. For example, in next code debugger become stopped in + rescue block, but program continues its execution. + +2007-12-25 23:40 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/stepping.rb, + doc/ruby-debug.texi, ext/ChangeLog, lib/ChangeLog, + test/stepping.cmd, test/stepping.right: Add step- and step+. + Document as well as the new toggle command. + +2007-12-25 23:39 Rocky Bernstein + + * cli/ruby-debug/commands/enable.rb: Add toggle requested by Anders + Lindgren. + +2007-12-25 23:36 Rocky Bernstein + + * ext/ruby_debug.c: Expermimental patch to address a problems + reported by Timur Shipilov, + Software engineer, Xored Software Inc.: + + When SystemExit exception is raised debugger become stopped and + stop method is called as many times, as a number of threads + running in + application. For example, in next code debugger become stopped in + rescue block, but program continues its execution. + + Example: + + # Stuff to set up debugger + begin + # if you throw another Exception here, all will be fine + exit + sleep 20 + rescue Exception + puts 'This line is not traced' + end + puts 'And this too' + + # Debugger.stop was implicitly called when SystemExit exception + was thrown + # So, there will be an runtime error + Debugger.stop + +2007-12-25 09:55 Rocky Bernstein + + * ChangeLog, cli/ruby-debug/commands/stepping.rb, + doc/ruby-debug.texi, emacs/rdebug-core.el, ext/ChangeLog, + lib/ChangeLog: Small doc fixes. + +2007-12-25 07:51 Rocky Bernstein + + * ChangeLog, ext/ChangeLog, lib/ChangeLog: Last commit before + 0.10.0 release. + +2007-12-25 02:51 Rocky Bernstein + + * AUTHORS, ChangeLog, README, ext/ChangeLog, lib/ChangeLog, + test/breakpoints.cmd, test/breakpoints.right: breakpoints.*: main + -> Object. Add bad Class name test + AUTHOR: Add Anders + README: note ruby-debug-extra. More precise (I think) + +2007-12-24 21:02 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/processor.rb, doc/ruby-debug.texi, + test/breakpoints.cmd, test/breakpoints.right: Fix bug in stopping + on a method name. Use this in the examples. + +2007-12-24 09:24 Rocky Bernstein + + * doc/Makefile.am, doc/primes.rb, doc/ruby-debug.texi: Add iterator + example. + +2007-12-24 04:12 Rocky Bernstein + + * doc/hanoi.rb, doc/ruby-debug.texi, doc/test-tri2.rb, doc/tri3.rb: + More work on reference guide. Correct spelling, add example + showing + scope frame (for Enumerable). Other small corrections. + + Check in programs used in documentation. + +2007-12-24 00:25 Rocky Bernstein + + * ChangeLog, Rakefile, ext/ChangeLog, lib/ChangeLog: Rakefile: set + up gem unit test for ruby-debug-base. Add file in test/ + so we could do the same for ruby-debug were it not for other + mysterious + problems. + +2007-12-23 22:19 Rocky Bernstein + + * Rakefile, emacs/rdebug-core.el: Rakefile: don't add html or pdf + to gem. Have to get from ruby-debug-extra. + Since we can't build it, it will cause problems when rake is run. + rdebug-core.el: remove gud control keys from secondary buffers. + C-P, C-N, C-F + should have their normal motion meanings. + +2007-12-23 17:33 Rocky Bernstein + + * CHANGES, ChangeLog, Makefile.am, Rakefile, doc, ext/ChangeLog, + lib/ChangeLog, svn2cl_usermap, test/test-columnize.rb, + test/test-ruby-debug-base.rb, test/test-ruby-debug.rb: Go over + packaging: + ChangeLogs for ruby-debug-base (in ext and lib) separate from CLI + ChangeLog + ChangeLogs now map userid to names + ruby-debug-base regression test included in ruby-debug-base + Columnize test separated. (It will disappear when ruby-debug + requires it + as an external) + +2007-12-22 17:07 Rocky Bernstein + + * CHANGES, doc/ruby-debug.texi: More typos. + +2007-12-22 16:14 Rocky Bernstein + + * doc/ruby-debug.texi, emacs/rdebug-core.el: More doc changes. + +2007-12-22 11:18 Rocky Bernstein + + * INSTALL.SVN, bin/rdebug, doc/rdebug.1, doc/ruby-debug.texi: + Correct lots of little typographical and spelling errors. + +2007-12-22 04:02 Rocky Bernstein + + * bin/rdebug, doc/rdebug.1, doc/ruby-debug.texi, + emacs/rdebug-core.el, test/tdebug.rb: Sort options in + alphabetical order. + rdebug-core.el: docstring elaboration + Revise Emacs section gain. + +2007-12-22 02:53 Rocky Bernstein + + * emacs/rdebug-core.el: Indentation. + +2007-12-21 23:01 Rocky Bernstein + + * Rakefile, bin/rdebug, doc/rdebug.1, doc/ruby-debug.texi, + test/tdebug.rb: Synchronize command options. + +2007-12-21 20:23 Rocky Bernstein + + * emacs/rdebug-core.el: Messed up on how to specify Ctrl-. + +2007-12-21 20:15 Rocky Bernstein + + * emacs/rdebug-core.el: Make more compatible with gdb-key-prefix + commands. + +2007-12-21 20:06 Rocky Bernstein + + * bin/rdebug, doc/ruby-debug.texi, test/quit.cmd, test/quit.right, + test/tdebug.rb, test/test-quit.rb: rdebug, tdebug: Prevent + tracing in the debugger if --no-quit is in effect. + rdebug, tdebug: --noquit => --no-quit, --nostop -> --no-stop + test/*quit* Add quit test. + ruby-debug.texi: Doc above changes, update --help lists (e.g. + 0.9.4 => 0.10.0) + +2007-12-21 14:19 Anders Lindgren + + * emacs/rdebug-core.el: The disabled entries in the menu, finally, + has got the right key bindings. + +2007-12-21 11:38 Rocky Bernstein + + * doc/ruby-debug.texi, emacs/rdebug-core.el, emacs/rdebug.el: + rdebug.el: correct file to autoload for rdebug-track-attach + rdebug-core.el: remove free-variable warning + ruby-debug.texi: Start Emacs Command section. + +2007-12-21 03:19 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug-track.el, emacs/rdebug.el: + rdebug-set-window-name of rdebug-core.el -> rdebug-track-attach + in + rdebug-track.el. + rdebug.el: add autoload. + +2007-12-20 18:17 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-test.el, emacs/rdebug.el: + Regression test-case added that ensures that elisp files are + properly indented, plus indentation fixes. + +2007-12-20 09:18 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug.el: rdebug-core.el: Get gud + commands in secondary buffer working by + pulling things from gud.el's common initialization into + rdebug-set-windows. + + rdebug.el had renamed *rdebugtrack* to rdebug-track + +2007-12-19 20:46 Anders Lindgren + + * emacs/rdebug-core.el: Added 'stop debugger' to the menu. Moved + common gud init code to new function + 'rdebug-common-initialization'. + +2007-12-19 18:04 Anders Lindgren + + * emacs/rdebug-core.el: Simple 'if' typo caused the sentinel not to + be added. + +2007-12-19 17:37 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug-test.el: rdebug-goto-entry-n + failed to go to 10 if there was no entry 1. Fixed and regression + test added for this. + +2007-12-19 13:09 Rocky Bernstein + + * emacs/rdebug-test.el: Add \n's in rdebug-goto-entry-test. Doesn't + change things though. + +2007-12-19 12:59 Rocky Bernstein + + * emacs/rdebug-test.el: Add some tests for recent Emacs bugs found. + +2007-12-19 07:55 Anders Lindgren + + * emacs/rdebug-core.el: rdebug-goto-entry-n didn't work in the + watch window. + +2007-12-18 20:38 Anders Lindgren + + * emacs/rdebug-core.el: Replaced all 'rdebug-goto-entry-' + functions with a generic one. If several digits are pressed in + sequence they are treated as a multi-digit number -- but only if + such a number exist. + +2007-12-18 19:10 Anders Lindgren + + * emacs/rdebug-core.el: New mechanism to pick the best window to + display the source in. + +2007-12-18 17:58 Anders Lindgren + + * emacs/rdebug-core.el: Split + `rdebug-populate-secondary-buffer-map' into two functions, one + simply sets the basic keys (named xxx-plain) and one defines the + all keys, including the prefixed keys, and the menu. + + `gud-prefix-key' is used instead of C-x C-a. + +2007-12-18 17:09 Anders Lindgren + + * emacs/rdebug-core.el: Output window (and all other secondary + windows) are now created with the correct mode. Source window now + has C-x C-a prefix. + +2007-12-18 08:39 Rocky Bernstein + + * cli/ruby-debug/commands/enable.rb, emacs/rdebug-core.el, + test/breakpoints.cmd, test/breakpoints.right: rdebug-core.el: + Remember position in breakpoint window + rest: Fix bugs in enable/disable commands and DRY code a little + bit. Better regression tests + (needed obviously) + +2007-12-18 06:58 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-core.el, emacs/rdebug-track.el, + emacs/rdebug.el: Remove rdebugtrack from rdebug-core and put in + its own file. + +2007-12-18 00:44 Rocky Bernstein + + * INSTALL.SVN: Instructions for building, testing, and installing + from Rubyforge's Subversion. + +2007-12-17 16:19 Rocky Bernstein + + * emacs/rdebug-core.el, emacs/rdebug.el: rdebug.el: move emacs test + here from core + rdebug-core.el: add C-x C-a common keys to all debugger buffers + number keys are bound on display expressions. + Watch expression -> Display expression + +2007-12-17 10:31 Rocky Bernstein + + * emacs, emacs/rdebug-core.el, emacs/rdebug.el: rdebug-core.el, + rdebug.el: adjust docstring to remove layout keys - there are + too many of them and may change. + rdebug.el: bind keys 0-9 to position to the corresponding line + (which may + adjusted for header offsets). + +2007-12-17 07:35 Anders Lindgren + + * emacs/rdebug-core.el: * Menu handling: If a key in bound in the + rdebug common map, that key + binding is presented in the menu. + + * Windows bug fix: `gud-rdebug-marker-regexp' couldn't handle + windows + paths containing a drive letter. + +2007-12-17 05:43 Rocky Bernstein + + * ext/ruby_debug.c: Doc typo. + +2007-12-17 05:40 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb, test/helper.rb, + test/info-var-bug.rb, test/info-var.cmd, test/info-var.right, + test/test-display.rb, test/test-info-var.rb, + test/test-stepping.rb: Fix another "INTERNAL ERROR" bug in using + inspect for local variables. + Add a more thorough regression test here. + + Simplify regression tests by adding a filter Proc to the + run_debugger helper. + +2007-12-16 21:47 Rocky Bernstein + + * cli/ruby-debug/commands/variables.rb: Another place where we need + to guard against a faulty "inspect" routine. + +2007-12-16 21:31 Rocky Bernstein + + * ., ChangeLog, cli/ruby-debug/commands/info.rb, doc, emacs, ext, + lib/ruby-debug-base.rb, test/helper.rb, test/info-var-bug.rb, + test/info-var.cmd, test/info-var.right, test/runall, + test/test-breakpoints.rb, test/test-display.rb, + test/test-help.rb, test/test-info-var.rb: Add "info variables + test". + + ruby-debug-base.rb: Not sure how test(?M, file) ever worked + before but change + to use File.stat(file).mtime + info.rb: ignore debugger variables which are sometimes set. + +2007-12-16 17:01 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb: Guard against buggy "inspect" + and "to_str" methods in "info variables". + +2007-12-16 12:10 Rocky Bernstein + + * emacs/rdebug-test.el: Was broken by the splitting rdebug.el into + rdebug.el and rdebug-core.el + +2007-12-16 12:02 Rocky Bernstein + + * cli/ruby-debug.rb: Fix syntax error with last commit. + +2007-12-16 12:01 Rocky Bernstein + + * cli/ruby-debug.rb: Make init file handling match gdb better and + the comment in run_init_script. + +2007-12-16 11:50 Rocky Bernstein + + * Makefile.am, cli/ruby-debug.rb, cli/ruby-debug/commands/info.rb, + doc/ruby-debug.texi, test/info.right: ruby-debug.rb: The plague + of MS Windows: HOMEDRIVE prepended to HOMEPATH. rdebug.ini used + here instead of .rdebugrc. + + info documentation and help strings revised + + Makefile.am: "test" is the same as "check" (Even though Emacs + testing is + still broken) + +2007-12-16 04:09 Rocky Bernstein + + * doc/ruby-debug.texi: Add "info" section. Rework Emacs section + more. + +2007-12-16 01:12 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/command.rb, emacs/rdebug-core.el, + test/helper.rb, test/tdebug.rb, test/test-breakpoints.rb, + test/test-display.rb, test/test-stepping.rb: test/*: Be more + precise about file paths rather than assume Unix conventions. + More regular about use of SRC_DIR. Had broken tests previously in + not + reinitializing SRC_DIR. + bin/rdebug: notstop misspelling. + command.rb: Don't assume that Emacs implies are using + annotations, or a specific + line width + rdebug-core.el: add variable to specify what you want the + debugger line width + to be + +2007-12-15 17:46 Anders Lindgren + + * cli/ruby-debug/command.rb, emacs/rdebug-core.el: In Emacs mode, + emit longer lines. The Variables and Watch windows no longer + wraps around, so long lines look good. + +2007-12-15 17:38 Anders Lindgren + + * emacs/rdebug-core.el: Font-lock support added in the Variables + and Watch windows. + +2007-12-15 15:28 Anders Lindgren + + * emacs/rdebug-core.el: Doc string and comment overhaul, including + running a spell-checker. + +2007-12-15 15:23 Anders Lindgren + + * emacs/Makefile.am: License refered to 'Bash', replaced it with + 'This program'. + +2007-12-15 14:24 Anders Lindgren + + * emacs/rdebug-core.el: Reindented and adopted to Emacs + conventions. (Now, 'indent-region' applied to the whole file + considers the entire file to be correctly indented.) + +2007-12-15 13:50 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug.el: * Added comments at the + beginnig of the file, describing the package. + + * Added common key bindings for Eclipse and NetBeans + compatibility, and + `rdebug-populate-common-keys-function' for controlling this. + + * Fixed some `defcustom' stuff. + + * Renamed the `rdebug-many-windows-layout-xxx' to + `rdebug-window-layout-xxx' + + * Removed unused variable `rdebug-temp-directory' + + * Added autoload of `turn-on-rdebugtrack-mode' to rdebug.el. + +2007-12-15 09:18 Rocky Bernstein + + * emacs/Makefile.am: Install rdebug-core.el and put in package. + +2007-12-14 17:14 Anders Lindgren + + * emacs/rdebug-core.el, emacs/rdebug.el: Renamed rdebug.el to + rdebug-core.el. New file rdebug.el is now startup code. + +2007-12-14 17:08 Anders Lindgren + + * emacs/rdebug.el: Updated the doc string of 'rdebug', plus other + small fixes. + +2007-12-14 11:56 Rocky Bernstein + + * configure.ac, doc/ruby-debug.texi, ext/ruby_debug.c: Change + version to 0.10.0 + +2007-12-14 09:03 Anders Lindgren + + * bin/rdebug: Type 'stript' => 'script' + +2007-12-14 07:34 Anders Lindgren + + * cli/ruby-debug/processor.rb: Fixed problem where debugger + messages ended up in the 'output' buffer. + +2007-12-14 03:22 Rocky Bernstein + + * CHANGES, configure.ac, doc/rdebug.1, doc/ruby-debug.texi, + ext/ruby_debug.c: ruby-debug.c, configure.ac, ruby-debug.texi: Up + version to 0.9.9 + rdebug.1: document --no-quit + ruby-debu.texi: More work on Emacs section. + +2007-12-14 02:36 Rocky Bernstein + + * emacs/rdebug.el: Mostly small typos. + + rdebug-set-window-configuration-state: Reduce use of 'debugger + for + rdebug-window-configuration-state, in case we want to expand + values. + + debug--setup-secondary-window-help-buffer: More accurate + single-letter + command names. Fix typo. + +2007-12-13 20:27 Rocky Bernstein + + * emacs/rdebug.el: A little closer to getting running from + rdebug-track working. Set + shell to be the command buffer. rdebug-set-windows probably + should be + more appropriately renamed. + +2007-12-13 20:03 Rocky Bernstein + + * emacs/rdebug.el: Doc typo. + +2007-12-13 13:53 Rocky Bernstein + + * bin/rdebug, emacs/rdebug.el: rdebug.el: Add --post-mortem option + by default + rdebug: Fix bug introduced in adding exception handling + (--no-quit) + +2007-12-13 13:30 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/processor.rb, doc/ruby-debug.texi: + ruby-debug.texi: Document --no-quit + processor.rb: Annotations aren't an Emacs thing + rdebug: handle exceptions even if --post-mortem not given (but + --no-quit is) + +2007-12-13 12:57 Anders Lindgren + + * emacs/rdebug.el: * The sub-menus specific to a secondary window + is only shown when that + window is active. + * The menu item "Run" is renamed to "Continue" to avoid confusion + for + debugger shell users. + * Break-point commands added to the menu. + * In addition to tracking the original window layout, the + debugger + window layout is also tracked. This allows the user to switch + between + the window layouts. The menu now has three entries: Original, + Debugger, and Initial debugger. The first two also have + radio-buttons! + (Internally, the function `rdebug-set-window-configuration-state' + does + most of the work, so it's easier for the functions that switch + layouts.) + * rdebug-quit now prompts, and uses the new "quit + unconditionally" command. + * The "display" window is now renamed to the "watch" window. + * Some keys are rebound (toggle breakpoint is now "t" since "SPC" + is step). + +2007-12-13 02:22 Rocky Bernstein + + * emacs/rdebug.el: Add --no-quit option. + +2007-12-13 02:20 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/info.rb, doc/ruby-debug.texi, + test/breakpoints.cmd, test/breakpoints.right, test/info.right, + test/test-ruby-debug.rb: doc/ruby-debug.texi: + *rdebug-display-program* -> rdebug-watch-program* + note that you can run help info and list info subcommands + control.rb: If unconditionally is given, no questions are asked + info.rb: add "info program" to give program execution status + rdebug: add --noquit which doesn't exit when the program + terminates + +2007-12-12 17:20 Rocky Bernstein + + * cli/ruby-debug/commands/eval.rb: Remove warning that appears when + $VERBOSE is set because we are redefining (potentially) a method. + +2007-12-12 13:12 Rocky Bernstein + + * doc/ruby-debug.texi, emacs/rdebug.el: rdebug.el: wasn't showing + Stack buffer. + ruby-debug.texi: update how to autoload + +2007-12-12 12:16 Rocky Bernstein + + * emacs/rdebug.el: Interim changes from Anders Lindgren: Add + debugger menu to Ruby + buffers. Add Output buffer to standard display. + +2007-12-11 16:47 Rocky Bernstein + + * doc/ruby-debug.texi: Start to revise GNU Emacs section. More work + is needed. + +2007-12-11 03:51 Rocky Bernstein + + * emacs/rdebug.el: Proposed revised key bindings for secondary + buffers. + +2007-12-10 18:53 Rocky Bernstein + + * emacs/rdebug.el: Add key binding for stack motion + +2007-12-10 03:23 Rocky Bernstein + + * doc/ruby-debug.texi, lib/ruby-debug-base.rb: doc changes. + +2007-12-07 21:30 Rocky Bernstein + + * cli/ruby-debug/processor.rb: Don't always show "starting" + annotation. + +2007-12-07 11:03 Rocky Bernstein + + * cli/ruby-debug/processor.rb, emacs/rdebug.el: processor.rb: Code + for "starting"/output annotation + rdebug.el: add my own style window + +2007-12-07 03:45 Rocky Bernstein + + * emacs/rdebug.el: From Anders Lindgren: + * Implemented new annotation, "starting", with a corresponding + Emacs + "output" buffer. + + * New variable `rdebug-many-windows-layout-function' makes the + window + layout user configurable. Three different layouts implemented, + rdebug-many-windows-layout-default, -conservative, and + -stack-of-secondary-windows. + +2007-12-06 01:14 Rocky Bernstein + + * emacs/rdebug.el: From Anders Lindgren: + * `gud-comint-buffer' is now buffer local in all secondary + buffers, + hopefully this will make `rdebug' more independent of other + processes + like `gdb'. + + * The restore window configuration variable now has three + possible + values, when set to :many (which is the new default) the window + configuration is only restored when `rdebug-many-windows' is + active. + + * The `edit variable' command, when reading from the minibuffer, + uses + the old value as the initial content. Mouse-1 is no longer bound + to + `edit' since that prevents a simple copy, instead mouse-2 and + mouse-3 + is used. + + * More robust window configuration restore system. Trace support + for + window configuration state changes added. + +2007-12-05 08:42 Rocky Bernstein + + * emacs/rdebug.el: Python->Ruby typos. + +2007-12-05 00:50 Rocky Bernstein + + * cli/ruby-debug/commands/enable.rb, test/display.cmd, + test/display.right, test/test-display.rb: Fix a couple of + display/undisplay bugs caught by regression testing. + +2007-12-05 00:06 Rocky Bernstein + + * cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/info.rb, cli/ruby-debug/processor.rb, + emacs/rdebug.el: From Anders Lindgren: + * Emacs primitive `window-configuration' used instead of + `frame-configuration' since the latter caused (among other + things) the + frame title to freeze. (The workaround for the buffer-list crash + is no + longer needed.) + + * The user can now switch between the secondary windows using + commands + bound to the capital letters B, C, D, R, V. The key ? displays a + help + buffer. + + * Commands to add, delete, and edit display (watch) expressions. + + Breakpoint regexp position change which broke goto-breakpoint. + display.rb, processor.rb: use nil for deleted displays, more + display + annotation + +2007-12-04 11:31 Rocky Bernstein + + * cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/enable.rb, doc/ruby-debug.texi, + test/breakpoints.cmd, test/breakpoints.right: enable/disable + default to "breakpoint" when no subcommand specified. + More rigorous test of the code. + + display.rb: Fix bug when Debugger.annotation not initially set. + + ruby-debug.texi: Document enable/disable and remove watchpoint + references. Other small changes. + +2007-12-04 02:51 Rocky Bernstein + + * cli/ruby-debug/commands/display.rb, emacs/rdebug.el: display.rb + Don't show display if annotate > 1 since this goes in the + annotation buffer. + rdebug.el: remove minor-most-alist indicator. + +2007-12-02 22:39 Rocky Bernstein + + * emacs/rdebug.el: * `rdebug' was added to the mode line of all + rdebug buffers, a shell buffer + where the mode was active will have `rdebug' twice in the mode + line. + + * In `rdebug-setup-windows', use `gud-target-name' instead of + variable + `gud-last-last-frame'. Not completely sure about this. + + * Make `rdebug-display-original-frame-configuration' a command. + + * Call `gud-sentinel' from rdebug-process-sentinel. + +2007-12-02 21:56 Rocky Bernstein + + * cli/ruby-debug/processor.rb: Show display values in display + annotation. + +2007-12-02 21:47 Rocky Bernstein + + * cli/ruby-debug/commands/enable.rb, + cli/ruby-debug/commands/info.rb, emacs/rdebug-test.el, + emacs/rdebug.el, ext/ruby_debug.c, test/breakpoints.cmd, + test/breakpoints.right: Allow enabling/disabling breakpoints. Add + unit test of enabling/disabling and + emacs regexp checking. Adjust rdebug.el accordingly. + +2007-12-02 11:45 Rocky Bernstein + + * cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/enable.rb, + cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/variables.rb: Add enable/disable commands + info: Show disabled display expressions (like gdb) + display: update help text + variables: remove _self from list of local variables. + +2007-12-02 11:00 Rocky Bernstein + + * emacs/rdebug.el: If `rdebug-restore-original-frame-layout' is + non-nil (on by default), + the original frame layout is restored when the debugger process + exits. If the user restarts `rdebug' several times, the first + frame + layout is restored. + + Fix the `rdebug-debug-enter' macro to make it possible to use + edebug + in its body. Workaround for a bug in list-buffers which could + crash if + the frame buffer list contained killed buffers. + + New feature and bug fixes from Anders Lindgren. + +2007-12-01 21:28 Rocky Bernstein + + * emacs/rdebug-test.el, emacs/rdebug.el: Add a marker-filter test. + From Anders Lindgren: some debugging instrumentation and a bug + fix when + editing instance variables. + More python references removed. + +2007-11-30 09:21 Rocky Bernstein + + * test/display.cmd, test/display.right: longer display test + +2007-11-30 09:15 Rocky Bernstein + + * Rakefile: Include tests into package ruby-debug. + +2007-11-30 09:08 Rocky Bernstein + + * cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/info.rb, cli/ruby-debug/processor.rb, + test/display.cmd, test/display.right, test/info.cmd, + test/info.right, test/test-display.rb: Correct "info display" + command and make it look more like gdb. + Show annotations on preloop even if they are empty. + Create a regression test for "display" commands. + +2007-11-30 04:03 Rocky Bernstein + + * cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/settings.rb, cli/ruby-debug/processor.rb, + doc/ruby-debug.texi, test/info.right: Add "info display". Allow + annotation level 3. (Both as gdb does) + Reduce unnecessary breakpoint (and stack size) stack size output. + +2007-11-30 01:53 Rocky Bernstein + + * emacs/rdebug.el: Was creating duplicate buffers. Patch courtesy + of Anders Lindgren + +2007-11-29 02:55 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/variables.rb, + cli/ruby-debug/processor.rb, doc/ruby-debug.texi, + emacs/rdebug.el, test/info.right: The old "info variables" is now + called "info global_variables" + "info variables" shows local and instance_variables + rdebug.el: "local"" buffer is now "variable" buffer + Annotation buffer now show "info variables" rather than "info + locals" + +2007-11-26 01:15 Rocky Bernstein + + * doc/rdebug.1: Add "up", and "down"; delete "clear" and add an + $Id$ line. + +2007-11-26 00:48 Rocky Bernstein + + * emacs/rdebug.el: Make sure we ahve emacs 22 or greater. + +2007-11-25 17:49 Rocky Bernstein + + * emacs/rdebug.el: Add $Id$ line + +2007-11-25 16:51 Rocky Bernstein + + * emacs/rdebug.el: Improve breakpoints buffer handling slightly. Is + now a major mode and + more like gdb-ui.el. + +2007-11-25 11:14 Rocky Bernstein + + * doc/ruby-debug.texi: typo step + => step+ + +2007-11-25 11:04 Rocky Bernstein + + * doc/ruby-debug.texi: Small corrections to Debugger.start section + +2007-11-24 11:01 Rocky Bernstein + + * ext/ruby_debug.c: Some documentation typos. + +2007-11-24 11:00 Rocky Bernstein + + * doc/rdebug.1, doc/ruby-debug.texi: *: Go over command options. + document annotation + ruby-debug.texi: Document Debugger.context + +2007-11-24 04:07 Rocky Bernstein + + * ext/ruby_debug.c: Ooops, forgot to do frame_locals and update the + rb_define_method + argument count in a couple of places. + +2007-11-24 03:00 Rocky Bernstein + + * Rakefile, doc/Makefile.am, doc/ruby-debug.texi, ext/ruby_debug.c, + test/test-ruby-debug.rb: ruby_debug.c: context.frame things now + allow the frame postion number to be optional. We'll assume 0 + (the top) as the default. + + test-ruby-debug.rb: add tests of the above an of these routines + in general. Make this + be able to run outside of rake. + + Rakefile: Removed emacs/elisp since that's now part of a + different package. + + doc/Makefile.am: Make manual page + + doc/ruby-debug.texi: try to clarify blocks/frames. Redo incorrect + frame passages as a result of vestiges of the bashdb manual. + +2007-11-23 02:43 Rocky Bernstein + + * Makefile.am, doc/Makefile.am, doc/rdebug.1, emacs/Makefile.am: + Make distcheck now works (tests building outside of source + regression tests installing and uninstalling) + rdebug.1: add manual page + +2007-11-22 13:49 Rocky Bernstein + + * emacs/Makefile.am, emacs/rdebug-test.el: rdebug-test.el: regexp + name changed. Fix test. + +2007-11-22 13:36 Rocky Bernstein + + * Makefile.am: Top-level ruby-trunk-extra automake file + +2007-11-22 13:27 Rocky Bernstein + + * autogen.sh: Make NEWS->CHANGES symlnk since NEWS is what + autotools wants. + +2007-11-22 13:22 Rocky Bernstein + + * autogen.sh, configure.ac, doc/Makefile.am, test/test-frame.rb: + test-frame.rb: remove debugging + rest - use autotools to configure a ruby-debug-extra package + which includes + documentation and GNU Emacs support. + +2007-11-22 13:00 Rocky Bernstein + + * emacs/Makefile.am, emacs/elisp-comp: Pick up from autotools + +2007-11-21 00:16 Rocky Bernstein + + * cli/ruby-debug/interface.rb: Make sure @histfile is initialized + before writing it. It could be uninitialized if entered via + Debugger.start; debugger + +2007-11-20 19:42 Rocky Bernstein + + * emacs/rdebug.el: define-minor-mode keymap doesn't work the way I + thought it would. rdebugrack-mode-text typo. + +2007-11-17 18:09 Rocky Bernstein + + * emacs/rdebug.el: Try using a define-minor-mode. (Not without some + problems + though). Shorten rdebug-rdebugtrack to rdebugtrack in case we + ever do + split out the emacs routines. + +2007-11-17 11:54 Rocky Bernstein + + * emacs/rdebug.el: Set --annotate=3 which is what it is in gdba + +2007-11-17 11:46 Rocky Bernstein + + * emacs/rdebug.el: Use and advise function to hook into gud-reset. + +2007-11-16 15:56 Rocky Bernstein + + * emacs/rdebug.el: Handle stack frame lines that split across two + lines. Make stack frame buffer have its own mode. + +2007-11-16 13:50 Rocky Bernstein + + * cli/ruby-debug/commands/method.rb: And make sure to use "inspect" + when showing instance variables as well. + +2007-11-16 13:48 Rocky Bernstein + + * cli/ruby-debug/commands/method.rb: Sort instance variables. + +2007-11-15 19:03 Rocky Bernstein + + * ext/ruby_debug.c: Fix misspelling of declared. + +2007-11-15 15:59 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/variables.rb, emacs/rdebug.el, + test/helper.rb, test/setshow.right, test/test-setshow.rb: + variables.rb: Add "self" to local variables (unless it's "main") + #12782 + http://rubyforge.org/tracker/index.php?func=detail&aid=12782&group_id=1900&atid=7436 + + info.rb: "info args" and "info locals" output should use inspect + (for arrays and such) + helper.rb: Show output lines if "$DEBUG" (ruby -d) is set. + require "fileutils" since we use it. + setshow.*: simplify test code using common helper.rb routine + + rdebug.el: Add key binding in comint buffer for the more common + kind of traceback + +2007-11-15 00:40 Rocky Bernstein + + * emacs/rdebug.el: Set point to current frame in stack window. + +2007-11-14 01:39 Rocky Bernstein + + * cli/ruby-debug/commands/settings.rb, doc/ruby-debug.texi, + test/setshow.cmd, test/setshow.right, test/test-setshow.rb: Add + 'set history save' and 'set history size'. + +2007-11-13 13:28 Rocky Bernstein + + * cli/ruby-debug/interface.rb: Make sure to convert string HISTSIZE + to a number - This time for sure! + +2007-11-13 13:16 Rocky Bernstein + + * test/setshow.cmd, test/setshow.right: Broke regression test + (actually, it was slightly broken even before.) + +2007-11-13 13:12 Rocky Bernstein + + * cli/ruby-debug/interface.rb: Follow gdb's history length setting + just a little bit closer. + +2007-11-12 14:51 Rocky Bernstein + + * cli/ruby-debug/commands/show.rb, test/setshow.right: Use on/off + to display history saving. + +2007-11-12 04:08 Rocky Bernstein + + * test/setshow.right: Forgot to update output check. + +2007-11-12 03:03 Rocky Bernstein + + * doc/ruby-debug.texi: Small change: Add a reference. + +2007-11-12 02:57 Rocky Bernstein + + * doc/ruby-debug.texi: Document "method iv" and "show history" + commands. + +2007-11-12 01:27 Rocky Bernstein + + * cli/ruby-debug/commands/show.rb, cli/ruby-debug/interface.rb, + doc/ruby-debug.texi, test/setshow.cmd, test/setshow.right, + test/test-setshow.rb: Add gdb-like "show history". We don't allow + set yet though. + +2007-11-09 18:27 Rocky Bernstein + + * cli/ruby-debug/commands/method.rb: Add "method iv" + (instance_variables) + +2007-11-07 12:08 Rocky Bernstein + + * Rakefile: DateTime -> Time. Patch #14983 Hiroshi NAKAMURA (nahi) + +2007-11-07 11:54 Rocky Bernstein + + * emacs/rdebug-test.el: Typo - loading wrong file name. + +2007-11-07 11:52 Rocky Bernstein + + * CHANGES, Rakefile, cli/ruby-debug/interface.rb, emacs/elisp-comp, + emacs/rdebug-track.el, emacs/rdebug.el: Rakefile: add emacs + compile task. Combine common package files into a variableg + to improve DRYness. + interface.rb: Apply Roger Pack's patch #12788 (add "." to + .rdebugsavehist if + other HOME and HOMEPATH aren't defined). + rdebug-track.el is now folded into rdebug.el so it's no longer + needed. + rdebug.el: remove compiler-detected bug + +2007-11-07 02:55 Rocky Bernstein + + * emacs/rdebug-test.el, emacs/rdebug.el: Add routine to goto a + unit/test traceback line + +2007-11-06 12:33 Rocky Bernstein + + * emacs/rdebug.el: rdebugtrack deletes annotations now. Other small + improvements. + +2007-11-06 02:07 Rocky Bernstein + + * emacs/rdebug-test.el, emacs/rdebug.el: Add routine to be parse + traceback position and go to it. + +2007-11-06 00:03 Rocky Bernstein + + * emacs/rdebug.el: cosmetic changes + +2007-11-05 19:12 Rocky Bernstein + + * emacs/rdebug.el: Add ability to edit locals value. Make more like + gud-ui.el + +2007-11-05 15:18 Rocky Bernstein + + * cli/ruby-debug/processor.rb, emacs/rdebug.el, test/test-help.rb: + rdebug.el: not all Emacs have split-string-and-unquote. + processor.rb, test-help.rb: Fix breakage from yesterday. Revert a + change + +2007-11-04 15:05 Rocky Bernstein + + * emacs/rdebug.el, test/test-help.rb: Expand/revise Emacs rdebug + docstring + test-help.rb: skip until we fix properly. + +2007-11-04 14:16 Rocky Bernstein + + * cli/ruby-debug/processor.rb, emacs/rdebug.el: Move prompt display + after preloop. + Make rdebugtrack work with annotations. + +2007-11-04 05:51 Rocky Bernstein + + * emacs/rdebug.el: Small nesting bug. + +2007-11-04 04:15 Rocky Bernstein + + * emacs/rdebug.el: Holdover from when three \032's are what we used + for annotation. (It's two now.) + +2007-11-04 04:05 Rocky Bernstein + + * emacs/rdebug-extra.el: rdebug-extra.el is no longer used. Has + been folded into rdebug.el + +2007-11-04 04:04 Rocky Bernstein + + * Rakefile, bin/rdebug, cli/ruby-debug.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, cli/ruby-debug/processor.rb, + emacs/rdebug-extra.el, emacs/rdebug-test.el, emacs/rdebug.el: + Debugger "annotation" mode. This is used for example in GNU Emacs + to + track the status of breakpoints, stack and local variables. But + it can + be used by other front-ends as well. The command-line option is + --annotate (-A) and there are set/show commands. + + Add emacs files to the package now. More complete Emacs code. + +2007-11-03 21:20 Rocky Bernstein + + * emacs/rdebug-test.el, emacs/rdebug.el, rdebug.el: Move to the + right place (under emacs) + +2007-11-03 21:19 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb, rdebug.el: First attempt to + update and redo the GNU Emacs-to-rdebug interface + +2007-10-31 03:15 Rocky Bernstein + + * Rakefile: Add emacs files to package + +2007-10-31 03:12 Rocky Bernstein + + * emacs/rdebug-extra.el, emacs/rdebug-test.el: Some test of emacs + rdebug regular expressions. + +2007-10-31 02:19 Rocky Bernstein + + * test/help.cmd: Can't handle "help info" this way. Ignore for now. + +2007-10-31 02:00 Rocky Bernstein + + * test/help.cmd, test/info.cmd, test/info.right, test/test-info.rb: + Add basic test of the info command. (Much more would be nice.) + +2007-10-28 04:29 Rocky Bernstein + + * emacs/rdebug-track.el: We don't use rdebug-safe - remove. + string-to-int -> string-to-number as + elisp compiler suggests. + +2007-10-12 10:41 Rocky Bernstein + + * doc/ruby-debug.texi: Add note regarding needing to specify the + 'main' class to set a breakpoint in a main routine. Some other + small formatting changes. + +2007-10-12 10:15 Rocky Bernstein + + * cli/ruby-debug/interface.rb, runner.sh, test/breakpoints.right, + test/test-breakpoints.rb: interface.rb: print is really printf + runner.sh: was using variable before setting it + test/*breakpoints*: first integration test of breakpoints. + +2007-10-12 01:45 Rocky Bernstein + + * ext/ruby_debug.c, test/breakpoints.cmd: Bug in setting a + breakpoint at a main method (e.g. main.gcd). Inside + breakpoint_by method we seem to get nil for the class name. The + fix + here is to change that to the string "main". Better might be to + have + that class name not be nil. + + test/breakpoints.cmd has a sequence of commands that when run on + gcd.rb will show the problem. + +2007-10-11 08:59 Rocky Bernstein + + * test/test-frame.rb: Name conflick in test class name. + +2007-10-11 01:07 Rocky Bernstein + + * test/frame.cmd, test/frame.right, test/helper.rb, + test/test-frame.rb: helper.rb: move out some common test routines + *frame*: add test of frame commands: up, down, frame + +2007-10-03 01:46 Rocky Bernstein + + * cli/ruby-debug/interface.rb, test/stepping.cmd, + test/stepping.right, test/test-stepping.rb: interface.rb: remove + trailing \n. + test-stepping.rb: remove some bugs in cheap-diff + test/stepping.*: don't need "next 1" or "step 1", check without + parameter. + +2007-09-30 13:09 Rocky Bernstein + + * test/test-stepping.rb: Simplify even more. + +2007-09-30 13:07 Rocky Bernstein + + * test/test-stepping.rb: We're not using Diff::LCS so comment it + out. + +2007-09-30 02:50 Rocky Bernstein + + * cli/ruby-debug.rb: Avoid duplicate constants which happens when + "rake test" is run. + +2007-09-30 02:48 Rocky Bernstein + + * cli/ruby-debug/interface.rb, runner.sh, test/gcd.rb, + test/stepping.cmd, test/stepping.right, test/tdebug.rb, + test/test-setshow.rb, test/test-stepping.rb: + cli/ruby-debug/interface.rb: add a verbose mode to show what + commands are + getting run. + + runner.sh: add the ability to set the rdebug script to run based + on environment + variable RDEBUG + + Both of the above are in support of adding the first integration + test + by running rdebug and comparing output produced. The first test + is of + commands in stepping.rb (step, next, finish). It is still a + little + hoaky and needs more work, but another step in the right + direction. + +2007-09-07 04:30 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, test/test-help.rb, + test/test-setshow.rb: control.rb: chdir back to directory where + initial run came from. + command.rb, settings.rb, show.rb info.rb: remove warnings when + running + regression tests (due to initializing constants more than once) + + test/*: Use File.join where appropriate + +2007-09-04 01:50 Rocky Bernstein + + * doc/ruby-debug.texi: Start filling out Debugger Module section. + In particular the settings Array. + +2007-09-03 15:29 Rocky Bernstein + + * doc/ruby-debug.texi: Better wording of step+ n. + +2007-09-03 15:06 Rocky Bernstein + + * doc/ruby-debug.texi: Update doc for recent changes. + +2007-09-03 15:06 Rocky Bernstein + + * CHANGES, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/help.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, cli/ruby-debug/processor.rb, + test/help.cmd, test/help.right, test/setshow.cmd, + test/setshow.right, test/test-help.rb: help "foo" gives message + "Undefined command "foo" rather than a list + of help commands. (Message test is gdb's) + + Add set linetrace+ - similar step+ for linetrace. Don't show + duplicate + lines. + +2007-08-28 10:28 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb: Get "ruby" from Gem.ruby if + that exists. + +2007-08-28 10:07 Rocky Bernstein + + * test/cmdparse.cmd, test/cmdparse.right, test/setshow.cmd, + test/setshow.right, test/test-cmd.rb, test/test-setshow.rb: + cmdparse -> setshow + +2007-08-28 10:05 Rocky Bernstein + + * Rakefile, test/cmdparse.cmd: Rakefile: Make test/check depend on + lib. Make more ruby like and remove + duplicate "clean" target. + +2007-08-28 03:07 Rocky Bernstein + + * test/cmdparse.cmd: Testing svn propset. + +2007-08-28 03:06 Rocky Bernstein + + * test/cmdparse.cmd: Add $Id$ line propset. + +2007-08-28 02:37 Rocky Bernstein + + * test/cmdparse.cmd, test/cmdparse.right, test/test-cmd.rb: Yay! + Start first real regression test. Here we are just trying out + some set/show commands. + +2007-08-27 01:58 Rocky Bernstein + + * doc/ruby-debug.texi: Add some command names on sample sessions. + +2007-08-27 00:48 Rocky Bernstein + + * doc/ruby-debug.texi: More in tutorial section: Add + Debugger.start, show step+ and mention + set forcestep on. + +2007-08-22 13:00 Rocky Bernstein + + * doc/ruby-debug.texi: Add note about putl running down rather than + across. + +2007-08-22 08:28 Rocky Bernstein + + * CHANGES, cli/ruby-debug/commands/irb.rb, + cli/ruby-debug/processor.rb, doc/ruby-debug.texi: leaving irb + shows position same as entering debugger; "list" position + is also cleared when leaving irb. + + Update documentation for the above but more generally to talk + about + the default position that is used in "list", And more + specifically the + frame command also resets the default position. + +2007-08-21 11:40 Rocky Bernstein + + * doc/ruby-debug.texi: Add some notes about the programming + examples. + +2007-08-18 14:57 Rocky Bernstein + + * doc/ruby-debug.texi: Small typos: + - add link to command files in .rdebugrc + - Debugger.debugger -> debugger + - help output is columnized + - remove duplicate "var global" + - Invode -> Invoke + +2007-08-14 03:19 Rocky Bernstein + + * doc/ruby-debug.texi: Make a stab at "var" and "method" commands. + +2007-08-08 09:28 Rocky Bernstein + + * doc/ruby-debug.texi: Start "ruby-debug/debugger" and unit test + section. Elaboration on + error messages when "set autoeval on" + +2007-08-08 07:58 Rocky Bernstein + + * test/test-ruby-debug.rb: Remove duplicate "include" + +2007-08-07 17:58 Rocky Bernstein + + * cli/ruby-debug/commands/display.rb: Better parsing of undisplay. + This time for sure. + +2007-08-07 17:44 Rocky Bernstein + + * cli/ruby-debug/commands/display.rb: Better parameters parsing for + the "undisplay" command. + +2007-08-06 11:23 Rocky Bernstein + + * doc/ruby-debug.texi: Add ruby-debug version number to title. Add + Example macro to allow for + better customization and flexibility. + +2007-08-05 22:10 Rocky Bernstein + + * ext/ruby_debug.c: Typo. + +2007-08-05 16:52 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb, doc/ruby-debug.texi: Work on + bugs in restart command. + Work on ruby-debug sample sessions. Much more work is still + needed though. + +2007-08-04 13:36 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/eval.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, + cli/ruby-debug/commands/stepping.rb, cli/ruby-debug/processor.rb, + doc/ruby-debug.texi, ext/ruby_debug.c: settings, processor, show: + display expressions should be shown when line tracing. To this + end change always_run from + a boolean on integer "level" number. + + eval.rb pc -> putl + + ruby_debug.c: replace a non-word in a comment its equivalent + ruby-debug.texi: document recent changes pc->putl, display + expresions appear when line tracing + +2007-07-21 19:18 Rocky Bernstein + + * doc/ruby-debug.texi: Work more on sample session. Start to + document ps and pc and set/show linetrace + +2007-07-21 14:50 Rocky Bernstein + + * CHANGES: *** empty log message *** + +2007-07-21 13:54 Rocky Bernstein + + * cli/ruby-debug/command.rb, ext/ruby_debug.c, runner.sh: Changes + to make ruby-debug work for 1.9 (at least minimally). + ruby_debug.c: parameter saving seems to have a bug in it. Don't + turn on by default. + runner.sh: set which ruby using environment variable RUBY. + +2007-07-19 03:08 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/eval.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, ext/ruby_debug.c: Add "set" + option to save scalar values and class names on each call. + Add pc (print columnized) and ps (print sorted columnized). + +2007-07-09 16:37 Rocky Bernstein + + * cli/ruby-debug/commands/show.rb: Guard against unitialized argv + setting - via Debugger.start? + +2007-07-02 15:34 Rocky Bernstein + + * cli/ruby-debug/helper.rb: "," -> ", ". This looks nicer. + +2007-06-27 13:44 Rocky Bernstein + + * doc/ruby-debug.texi: Start section on GNU Emacs. + +2007-06-27 12:46 Rocky Bernstein + + * cli/ruby-debug.rb, doc/ruby-debug.texi: Note recent change to run + HOME *after* a local init file. + +2007-06-26 07:05 Rocky Bernstein + + * CHANGES, bin/rdebug, cli/ruby-debug.rb, lib/ruby-debug-base.rb: + Run .rdebugrc on Debugger.start. Look for this in the current + directory and run that instead the one in $HOME if that exists. + Again, inspired and compatible with gdb. + + rdebug: Check script for syntax errors before loading. We get + more informative errors and it doesn't look like rdebug is at + fault. + +2007-06-25 10:25 Rocky Bernstein + + * doc/ruby-debug.texi: Fill out more set/show commands. + +2007-06-21 11:30 Rocky Bernstein + + * CHANGES: Node script->source. + +2007-06-21 11:25 Rocky Bernstein + + * cli/ruby-debug/commands/script.rb: Some small changes missing + from last update. script->source and change help + wording slightly. + +2007-06-21 11:19 Rocky Bernstein + + * doc/ruby-debug.texi: Document source command and command files. + Break out "Controlling the debugger" into separate sections. Go + over + command index entries. + +2007-06-21 10:39 Rocky Bernstein + + * Rakefile, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/script.rb, doc/ruby-debug.texi, + ext/ruby_debug.c, test/test-ruby-debug.rb: test-ruby-debug.rb, + Rakefile: revise so "rake test" works with recent reorganization. + ruby-debug.c: remove unused variable declaration (and compile + warning) + command.rb: remove a warning given when "$DEBUG" or warnings are + set + script.rb: rename "script" to "source" to be more in line with + gdb + ruby-debug.texi: document "source" command, .rdebugrc and how + command files + work. + +2007-06-05 18:54 Kent Sibilev + + * cli/ruby-debug/helper.rb: moved utility modules to helper.rb + +2007-06-05 16:36 Kent Sibilev + + * bin/rdebug, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/display.rb, + cli/ruby-debug/commands/eval.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/help.rb, cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/method.rb, + cli/ruby-debug/commands/script.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, + cli/ruby-debug/commands/stepping.rb, + cli/ruby-debug/commands/threads.rb, + cli/ruby-debug/commands/variables.rb, + cli/ruby-debug/interface.rb, cli/ruby-debug/processor.rb, + ext/ruby_debug.c, lib/ruby-debug-base.rb: code reorganization. + reverted 'run' command. + +2007-06-05 07:59 Kent Sibilev + + * lib/ruby-debug-base.rb: restore post_mortem + +2007-06-05 04:28 Rocky Bernstein + + * cli/ruby-debug/processor.rb: Put back print statements the way + they were. It seems important to use + commas in print statments and not %. + +2007-06-05 03:48 Kent Sibilev + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/control.rb, + ext/ruby_debug.c: tabs to spaces + changed copy.args to play nicely with GC + +2007-06-04 14:52 Rocky Bernstein + + * cli/ruby-debug/processor.rb: Fix bug: When line contains format + strings like %s, print thinks there were too few arguments. + Fix by expanding % to %% and creating a print1 routine which + takes one parameter. + Not sure if this is the best fix. + + Traceback: + INTERNAL ERROR!!! too few arguments + /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.9.4/cli/ruby-debug/interface.rb:12:in + `printf' + /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.9.4/cli/ruby-debug/interface.rb:12:in + `print' + /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.9.4/cli/ruby-debug/processor.rb:104:in + `print' + /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.9.4/cli/ruby-debug/processor.rb:96:in + `__at_line' + +2007-06-04 11:52 Rocky Bernstein + + * cli/ruby-debug/commands/settings.rb, doc/ruby-debug.texi: + ruby-debug.texi: Start listing "set" commands. + settings.rb: change basename help + +2007-06-04 00:06 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/commands/control.rb: Small bug in + setting ARGV on restart. + +2007-06-03 23:50 Rocky Bernstein + + * bin/rdebug: Catch all uncaught exceptions in rdebug's top-level + run loop. + +2007-06-03 11:50 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/commands/control.rb, + cli/ruby-debug/interface.rb: Allow run when there is more than + one thread. + Disallow run unless called from rdebug. + Reset ARGV on run. + +2007-06-03 02:44 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/commands/control.rb, + cli/ruby-debug/processor.rb, ext/ruby_debug.c: Get warm restart + working for one thread - it might even work on OSX ;-) + +2007-06-02 22:43 Rocky Bernstein + + * cli/ruby-debug/command.rb: Typo. + +2007-06-02 16:14 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb, cli/ruby-debug/processor.rb: Add + routine to canonicalize file name. This also helps out Emacs. + Independent it's useful to have a place to funnel how to show + filenames. Add set basename to allow short filename setting which + will be useful in regression tests. + +2007-06-02 15:01 Rocky Bernstein + + * cli/ruby-debug/processor.rb, emacs/rdebug-track.el, + lib/ruby-debug-base.rb: lib/ruby-debug-base.rb: add Quit and + Restart exceptions which can reliably be used after the delayed + exception handling bug is fixed + emacs/rdebug-track.el and cli/ruby-debug/processor.rb: more + accurate line tracking in EMACS. When not in emacs should be more + like what was there. + +2007-06-01 21:57 Rocky Bernstein + + * lib/ruby-debug-base.rb: parens around a print seems to give a + warning. Remove. + +2007-05-31 02:21 Rocky Bernstein + + * CHANGES: Typo. + +2007-05-31 02:15 Rocky Bernstein + + * CHANGES, cli/ruby-debug/processor.rb: Add Emacs locations on + breakpoints and catchpoints + +2007-05-30 16:21 Rocky Bernstein + + * cli/ruby-debug/command.rb: Debug statement creapt in. + +2007-05-30 16:15 Rocky Bernstein + + * cli/ruby-debug/command.rb, runner.sh: runner.sh - allow running + outside of trunk directory + command.rb: do better about putting "at line" on another line + when we overflow the line width. + +2007-05-30 06:05 Rocky Bernstein + + * test/test-ruby-debug.rb: Columnize *has* been added. + +2007-05-30 05:50 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/commands/settings.rb: Oops another bug + if no "set" parameter has been given. + "set autoirb on" seems to mess up syntax checking. + +2007-05-30 05:21 Rocky Bernstein + + * cli/ruby-debug/commands/settings.rb: arg -> args + +2007-05-27 18:37 Rocky Bernstein + + * bin/rdebug: Catch uncaught exceptions in main loop. + +2007-05-27 15:56 Rocky Bernstein + + * runner.sh: Pass back $? from ruby-debug. + +2007-05-27 15:53 Rocky Bernstein + + * bin/rdebug: Make sure Ruby script syntax checks okay. Otherwise + we get a load + message that looks like rdebug has a problem. + +2007-05-27 14:36 Rocky Bernstein + + * bin/rdebug, runner.sh: Fix bug in ignoring "-r debug" + +2007-05-26 22:18 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/show.rb: Add + show version. + +2007-05-26 22:00 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/list.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb: Add set args and set listsize. + +2007-05-26 20:38 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/control.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb: command.rb, show.rb: Add show + args + control.rb: back off on using AR + +2007-05-26 13:56 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb: Set now allows "on", "off", 1 or + 0. + Add set/show linetrace + Add show keep-frame-bindings, port, port-mortem. + +2007-05-26 04:54 Rocky Bernstein + + * doc/ruby-debug.texi: Document --keep-frame-binding better. + +2007-05-26 04:42 Rocky Bernstein + + * cli/ruby-debug/commands/info.rb: Introduced bug after reworking + "info args". make "local args" truncate + output if it's too long same as info args. + +2007-05-26 04:17 Rocky Bernstein + + * CHANGES: Recent batch of changes. + +2007-05-26 03:22 Rocky Bernstein + + * bin/rdebug, cli/ruby-debug/commands/breakpoints.rb: + breakpoints.rb: break with no arguments sets a breakpoint at the + current line + same as gdb + rdebug: if there's a tty and no stop restart the program when it + finishes + +2007-05-25 13:48 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb: Go over errror messages. + +2007-05-25 13:43 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb: If prepending a ruby command + on restart, add "-I" for each $: + Check to see of Debugger::PROG_SCRIPT exists and is executable. + +2007-05-25 12:35 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb: Fix some small bugs. restart + still has problems though. + +2007-05-25 12:21 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb: Fix small bug in restart + parameter passing i introduced. + +2007-05-25 10:11 Rocky Bernstein + + * cli/ruby-debug/commands/control.rb: Allow restart to work more + often. + +2007-05-25 09:34 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb: Reduce the redundancy a little + between set and show. + +2007-05-25 08:50 Rocky Bernstein + + * cli/ruby-debug/command.rb, cli/ruby-debug/commands/info.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/show.rb: Add info and show commands with + subcommands. + Setting subcommands made to be more like info and show (and gdb). + +2007-05-25 07:48 Rocky Bernstein + + * cli/ruby-debug/command.rb, ext/ruby_debug.c: Have to back off + from showing parameter values since we are showing the + dynamic value. So instead we show the paramater class. + + It should be possible to show the value however if + --keep-frame-bindings is + true. + +2007-05-25 06:45 Rocky Bernstein + + * Rakefile: rake check is a synonym for rake test + +2007-05-24 18:11 Rocky Bernstein + + * cli/ruby-debug/command.rb: This Ruby, not Perl: "last" => "break" + +2007-05-24 13:03 Rocky Bernstein + + * Rakefile, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/help.rb, + cli/ruby-debug/commands/method.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/threads.rb, + cli/ruby-debug/commands/variables.rb, ext/ruby_debug.c: Add + sandbox for rocky to work in + +2007-05-23 16:43 Rocky Bernstein + + * lib/ruby-debug-base.rb: post_mortem: to test $! *before* running + debug_at_ext or else we may get an erroneous message: + ruby-debug-base.rb:162:in `current_context': Debugger.start is + not called yet. (RuntimeError) + + A simple test case to show the problem: + + "require rubygems" + "require ruby-debug" + Debugger.start + Debugger.post_mortem + exit # Causes us to incorrectly give the above error + +2007-05-23 02:46 Rocky Bernstein + + * doc/ruby-debug.texi: Slogging on with the doc - further with the + example such as it is. + +2007-05-23 02:29 Rocky Bernstein + + * emacs/elk-test.el: test/unit for emacs. + +2007-05-23 02:20 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb: Fix type conversion + problem with comparing Fixnum with String. I + really need to start pushing forward on the regression tests. + +2007-05-22 12:28 Rocky Bernstein + + * test, test/test-ruby-debug.rb: Some rudimentary tests. + +2007-05-22 12:28 Rocky Bernstein + + * emacs, emacs/rdebug-track.el: Tracks rdebug debugger in an Emacs + shell window + +2007-05-22 02:17 Rocky Bernstein + + * doc/ruby-debug.texi: Make a stab at documenting the list command. + +2007-05-21 17:56 Rocky Bernstein + + * doc/ruby-debug.texi: Small changes. Explain thread number in + prompt. User input in examples + is bold. + +2007-05-21 13:42 Rocky Bernstein + + * bin/rdebug: Using long option --verbose without a script says you + need a script. + -v doesn't (same as --version). + +2007-05-20 17:17 Rocky Bernstein + + * cli/ruby-debug/commands/threads.rb: Stray debug output got + inserted accidentally. + +2007-05-20 17:01 Rocky Bernstein + + * cli/ruby-debug/commands/stepping.rb: Wasn't returning on a bad + continue argument. + +2007-05-20 16:45 Rocky Bernstein + + * cli/ruby-debug/commands/breakpoints.rb, doc/ruby-debug.texi: + breakpoints.rb: delete now will take a list + of breakpoint numbers. We now check file and line numbers to make + sure they + exist before adding a breakpoint. Overall make more gdb + compatible and use + gdb-like wording in giving status and error output. + + ruby-debug.texi: document break, catch and delete. Extend sample + session a little. + +2007-05-18 09:20 Rocky Bernstein + + * CHANGES: What's up. + +2007-05-18 09:13 Rocky Bernstein + + * cli/ruby-debug/commands/threads.rb, doc/ruby-debug.texi: More + minor tweaks to thread regexps. Allows "thread" and "thread nnn" + work + +2007-05-18 08:52 Rocky Bernstein + + * cli/ruby-debug/commands/threads.rb, doc/ruby-debug.texi: + threads.rb: hoist common thread number parse routines + +2007-05-18 02:34 Rocky Bernstein + + * cli/ruby-debug/commands/threads.rb: Go over regexps to make + errors make more sense. Use getint. Common + code needs refactoring. + +2007-05-17 14:03 Rocky Bernstein + + * bin/rdebug: -d option: turns on $DEBUG + -v option: print version number, then turn on verbose mode + ($VERBOSE) + --verbose turns on verbose mode ($VERBOSE) + --version works the same + --verbose turns on verbose mode ($VERBOSE) + +2007-05-17 03:55 Kent Sibilev + + * ext/ruby_debug.c: removed debug message + +2007-05-16 00:27 Kent Sibilev + + * cli/ruby-debug/commands/stepping.rb: wrong module to include + +2007-05-15 20:22 Kent Sibilev + + * CHANGES, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/breakpoints.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/stepping.rb, + cli/ruby-debug/commands/threads.rb, + cli/ruby-debug/commands/variables.rb, lib/ruby-debug-base.rb: + various fixes + +2007-05-09 16:56 Kent Sibilev + + * CHANGES, bin/rdebug, ext/ruby_debug.c: '-r' option can be used to + require additional libraries + +2007-05-02 17:36 Kent Sibilev + + * cli/ruby-debug.rb: expand path before running the script + +2007-04-28 00:32 Kent Sibilev + + * CHANGES: + +2007-04-27 23:30 Kent Sibilev + + * bin/rdebug: added option to not start control thread by default + +2007-04-27 23:21 Kent Sibilev + + * lib/ruby-debug-base.rb: ditto + +2007-04-27 23:20 Kent Sibilev + + * CHANGES: ditto + +2007-04-27 23:19 Kent Sibilev + + * lib/ruby-debug-base.rb: add breakpoint method as an alias for + debugger in case breakpoint method is not defined already + +2007-04-27 21:03 Kent Sibilev + + * cli/ruby-debug/commands/irb.rb: better name + +2007-04-27 20:59 Kent Sibilev + + * cli/ruby-debug/commands/irb.rb: make sure we dont throw in a + wrong context + +2007-04-27 20:43 Kent Sibilev + + * cli/ruby-debug.rb, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/eval.rb, cli/ruby-debug/commands/irb.rb: + fixed rdoc + +2007-04-27 20:31 Kent Sibilev + + * CHANGES, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/eval.rb, + cli/ruby-debug/commands/frame.rb, cli/ruby-debug/commands/irb.rb, + cli/ruby-debug/commands/list.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/stepping.rb: - irb 'cont' command + continues execution without showing the debugger prompt. + - added Debugger.settings method to programatically modify + command settings + +2007-04-27 06:14 Kent Sibilev + + * CHANGES: note the latest changes + +2007-04-27 06:12 Kent Sibilev + + * bin/rdebug: Compatibility with Ruby-distributed debug module + +2007-04-27 06:07 Kent Sibilev + + * ext/ruby_debug.c: Ctrl-C exits irb and continutes execution + bypassing the debugger prompt + +2007-04-27 06:07 Kent Sibilev + + * cli/ruby-debug/commands/irb.rb: Ctrl-C exits irb and continutes + execution bypassing the debugger prompt + +2007-04-07 23:21 Kent Sibilev + + * ext/ruby_debug.c: removed wrong if node check + +2007-04-04 20:23 Kent Sibilev + + * CHANGES, ext/ruby_debug.c: added hit conditions to breakpoints + +2007-04-03 18:07 Kent Sibilev + + * CHANGES: ditto + +2007-04-03 18:05 Kent Sibilev + + * ext/ruby_debug.c: Fixed file comparision on Windows platform + +2007-04-03 02:58 Kent Sibilev + + * CHANGES: typo + +2007-04-03 01:48 Kent Sibilev + + * CHANGES, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/settings.rb, + cli/ruby-debug/commands/stepping.rb, ext/ruby_debug.c: Added + force parameter to stepping commands + +2007-04-03 01:16 Kent Sibilev + + * CHANGES, cli/ruby-debug/commands/stepping.rb, ext/ruby_debug.c: + added force option to Context#step_over + +2007-04-02 20:55 Kent Sibilev + + * CHANGES, cli/ruby-debug/commands/breakpoints.rb, + ext/ruby_debug.c: fixed incorrect stack calculation + break help fix + +2007-04-01 17:15 Kent Sibilev + + * cli/ruby-debug/commands/help.rb: + +2007-04-01 17:10 Kent Sibilev + + * cli/ruby-debug/commands/eval.rb: + +2007-04-01 17:08 Kent Sibilev + + * cli/ruby-debug/commands/eval.rb, cli/ruby-debug/interface.rb, + cli/ruby-debug/processor.rb: expose two functions dbg_print and + dbg_puts that might be useful in the remote mode + +2007-03-30 15:09 Kent Sibilev + + * CHANGES: + +2007-03-30 08:03 Kent Sibilev + + * ext/ruby_debug.c: + +2007-03-30 07:40 Kent Sibilev + + * ext/ruby_debug.c: + +2007-03-30 07:39 Kent Sibilev + + * ext/ruby_debug.c: + +2007-03-30 07:21 Kent Sibilev + + * CHANGES, ext/ruby_debug.c: All Ruby's 'eval' and require/load + methods create a new frame. + +2007-03-29 20:50 Kent Sibilev + + * CHANGES, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/settings.rb: added frameclassname setting + +2007-03-29 02:50 Kent Sibilev + + * cli/ruby-debug/commands/stepping.rb: + +2007-03-29 02:49 Kent Sibilev + + * cli/ruby-debug/commands/stepping.rb: + +2007-03-29 02:09 Kent Sibilev + + * CHANGES, cli/ruby-debug/command.rb, + cli/ruby-debug/commands/frame.rb, + cli/ruby-debug/commands/settings.rb, ext/ruby_debug.c: Added new + Context.frame_class method + + 'frame' command will display a class name along with method name + + Added new 'fullpath' setting. + +2007-03-29 00:45 Kent Sibilev + + * CHANGES, ext/ruby_debug.c: too many internal changes require a + new major release + +2007-03-29 00:27 Kent Sibilev + + * ext/ruby_debug.c: remove useless stops when performing + 'step_over' operation + +2007-03-28 20:36 Kent Sibilev + + * CHANGES, cli/ruby-debug/commands/stepping.rb, ext/ruby_debug.c: + Added the possibility to add a temporary context-specific + breakpoint. + + Context#breakpoint and Context#set_breakpoint methods are added. + + 'cont' command now accepts a numerical parameter which implements + 'Continue until line' behavior. + +2007-03-27 23:26 Kent Sibilev + + * ext/ruby_debug.c: fixed previous optimization for Proc objects + +2007-03-27 23:22 Kent Sibilev + + * ext/ruby_debug.c: we don't need to create a new frame if there is + no block for a c-call + +2007-03-27 23:08 Kent Sibilev + + * CHANGES, ext/ruby_debug.c: Calling a method with a block will + create a new frame. This changes the behavior of 'next' command. + So in order to step into a block, 'step' command must be used. + That fixes bug #9629. + +2007-03-27 22:50 Kent Sibilev + + * ext/ruby_debug.c: step over shouldn't check that we moved to + another line + +2007-03-26 14:27 Kent Sibilev + + * ext/ruby_debug.c: ditto + +2007-03-26 04:51 Kent Sibilev + + * CHANGES: + +2007-03-26 02:51 Kent Sibilev + + * ext/ruby_debug.c: the frame must be captured when calling + Proc#call method + +2007-03-25 01:03 Kent Sibilev + + * lib/ruby-debug-base.rb: will start the debugger if necessary + +2007-03-24 18:23 Kent Sibilev + + * CHANGES: + +2007-03-24 18:17 Kent Sibilev + + * .: stable becomes the trunk + +2007-03-24 18:11 Kent Sibilev + + * + +2007-03-24 18:03 Kent Sibilev + + * ported stop reason from the trunk + +2007-03-19 08:05 Kent Sibilev + + * + +2007-03-19 07:59 Kent Sibilev + + * + +2007-03-19 07:46 Kent Sibilev + + * fixes processor to handler renaming + added a shortcut module + +2007-03-15 04:00 Kent Sibilev + + * + +2007-03-15 02:59 Kent Sibilev + + * + +2007-03-15 02:58 Kent Sibilev + + * added 'set autoirb' setting + +2007-03-15 02:46 Kent Sibilev + + * + +2007-03-15 02:39 Kent Sibilev + + * + +2007-03-15 02:32 Kent Sibilev + + * + +2007-03-15 02:32 Kent Sibilev + + * fixed help command + +2007-03-13 17:06 Kent Sibilev + + * missing file + +2007-03-13 17:06 Kent Sibilev + + * fixed rdoc + +2007-03-06 22:15 Kent Sibilev + + * updated help for list and eval commands + +2007-03-06 19:51 Kent Sibilev + + * pass the current state to the interface object if it accepts it + +2007-03-01 23:44 Kent Sibilev + + * fixed post-mortem + +2007-02-27 08:02 Kent Sibilev + + * repackaging ruby-debug + +2007-02-23 20:56 Kent Sibilev + + * added an option for Debugger.debug_load to stop at the first line + of code + +2007-02-12 06:59 Kent Sibilev + + * added --emacs option + +2007-02-09 16:56 Kent Sibilev + + * in remote mode the debugger shouldn't stop inside of rdebug + script + +2007-02-09 06:59 Kent Sibilev + + * + +2007-02-09 06:20 Kent Sibilev + + * -- + +2007-02-09 01:00 Kent Sibilev + + * fixed code reloading + made 'reload on' as a part of the 'set' command + evaluate ~/.rdebugrc as an init script + +2007-02-07 02:42 Kent Sibilev + + * should use ignored? method to check for the debugger's thread + +2007-02-06 22:21 Kent Sibilev + + * + +2007-02-05 22:48 Kent Sibilev + + * -- + +2007-02-05 22:11 Kent Sibilev + + * fixed emacs integration + +2007-02-05 20:40 Kent Sibilev + + * -- + +2007-02-05 20:38 Kent Sibilev + + * -- + +2007-02-05 20:34 Kent Sibilev + + * -- + +2007-02-05 20:16 Kent Sibilev + + * fixed another issue where a bogus frame is being left in the + stack + +2007-02-05 08:08 Kent Sibilev + + * should save frame id as well + +2007-02-05 07:55 Kent Sibilev + + * fix stack corruption error + +2007-02-05 01:16 Kent Sibilev + + * store frame's self and dyna_vars along with file/line information + +2007-02-04 23:36 Kent Sibilev + + * seg fault bugfixes + fixed suspend/resume + +2007-02-04 05:06 Kent Sibilev + + * restore prev patch + +2007-02-04 03:49 Kent Sibilev + + * -- + +2007-02-04 03:49 Kent Sibilev + + * A better fix for the segmentation fault + +2007-02-03 22:02 Kent Sibilev + + * found a better patch + +2007-02-03 20:33 Kent Sibilev + + * -- + +2007-02-03 20:24 Kent Sibilev + + * fix seg fault by avoiding ruby's bug + fixed Context#resume + when handling post-mortem all threads must be suspended + +2007-02-02 18:47 Kent Sibilev + + * removed ambiguity with down command + +2007-02-01 23:48 Kent Sibilev + + * typo + +2007-02-01 23:10 Kent Sibilev + + * changes for build 0.7 + +2007-02-01 22:15 Kent Sibilev + + * made eval command available from the control thread + +2007-02-01 17:30 Kent Sibilev + + * fixed dllexport for windows platform + +2007-02-01 15:49 Kent Sibilev + + * ditto + +2007-02-01 07:22 Kent Sibilev + + * added setting command + added Context#suspended? method + dispay suspended status in the thread list + display frame starting from zero + +2007-01-31 22:12 Kent Sibilev + + * store object ids in VALUE type + +2007-01-31 21:13 Kent Sibilev + + * ditto + +2007-01-31 21:12 Kent Sibilev + + * fixed help command + +2007-01-31 21:04 Kent Sibilev + + * ditto + +2007-01-31 20:44 Kent Sibilev + + * make a deep copy when capturing post mortem context + +2007-01-31 19:39 Kent Sibilev + + * fixed frame count + added frame_self method to context + +2007-01-31 16:48 Kent Sibilev + + * removed all references to frames array + fixed post-mortem debugging + +2007-01-31 00:51 Kent Sibilev + + * removed obsolete frames usage + +2007-01-31 00:41 Kent Sibilev + + * refactored out frame class and preallocate stack + made local variable available even when bindings are not + collected. + +2007-01-28 20:25 Kent Sibilev + + * -- + +2007-01-28 06:22 Kent Sibilev + + * - Control thread is always started by rdebug script. + - Ability to specify negative frame number to frame commands. + Patch from R. Bernstein. + +2007-01-28 04:59 Kent Sibilev + + * -- + +2007-01-28 04:52 Kent Sibilev + + * added top frame caching + control thread is always started by rdebug script + +2007-01-28 01:21 Kent Sibilev + + * + +2007-01-27 02:21 Kent Sibilev + + * -- + +2007-01-27 01:43 Kent Sibilev + + * another performance optimization + +2007-01-26 20:28 Kent Sibilev + + * fixed #7484 + +2007-01-26 19:31 Kent Sibilev + + * -- + +2007-01-26 17:59 Kent Sibilev + + * revisited file name comparing procedure + +2007-01-26 09:03 Kent Sibilev + + * performance improvements + +2007-01-26 03:12 Kent Sibilev + + * added option to exclude collecting of frame bindings + +2007-01-25 01:41 Kent Sibilev + + * small optimization + +2007-01-25 00:55 Kent Sibilev + + * remove the live thread ref from locker structure as well + +2007-01-24 20:42 Kent Sibilev + + * don't keep a ref to a live thread. + check contexts that their threads are alive + +2007-01-24 18:47 Kent Sibilev + + * ditto + +2007-01-24 18:33 Kent Sibilev + + * disable tracing when in post-mortem + added -x/--trace option to rdebug script + +2007-01-21 08:35 Kent Sibilev + + * updated changelog + +2007-01-21 08:13 Kent Sibilev + + * + +2007-01-21 03:34 Kent Sibilev + + * assign an id to the breakpoint + +2007-01-21 01:20 Kent Sibilev + + * added post_mortem_method wrap method + +2006-12-21 20:30 Kent Sibilev + + * fix of restart command for windows platform + +2006-12-21 20:16 Kent Sibilev + + * added 'restart' command + +2006-12-21 14:24 Kent Sibilev + + * update changelog + +2006-12-21 14:12 Kent Sibilev + + * made 'exit' an alias to 'quit' + fixed the interoperability problem with rspec + +2006-12-21 13:43 Kent Sibilev + + * fixed trace command in post-mortem mode + +2006-12-21 02:00 Kent Sibilev + + * updated changelog + +2006-12-21 01:59 Kent Sibilev + + * initialize only once + +2006-12-21 01:08 Kent Sibilev + + * fixes irb help command + +2006-12-20 21:19 Kent Sibilev + + * check that debugger has been started + +2006-12-20 20:41 Kent Sibilev + + * + +2006-12-20 20:14 Kent Sibilev + + * bumped version + +2006-12-20 20:08 Kent Sibilev + + * added post-mortem option to rdebug + +2006-12-20 19:38 Kent Sibilev + + * initial support for post-mortem debugging + +2006-12-19 06:13 Kent Sibilev + + * removed 'run' alias + +2006-12-18 08:34 Kent Sibilev + + * added irb command + fixed source_for method + +2006-12-02 19:15 Kent Sibilev + + * added reload command + +2006-12-02 18:32 Kent Sibilev + + * fixed #6518 and #6545 + +2006-12-01 06:49 Kent Sibilev + + * + +2006-12-01 06:47 Kent Sibilev + + * + +2006-11-21 23:29 Kent Sibilev + + * ensure that on/off is the last on the line + +2006-11-16 00:04 Kent Sibilev + + * fixed debug_method for assignment methods + +2006-11-16 00:01 Kent Sibilev + + * added the new branch for the stable version + +2006-10-15 22:43 Kent Sibilev + + * branching a stable version + +2006-10-15 22:26 Kent Sibilev + + * ext/win32/ruby_debug.so, lib/ruby-debug.rb: remove unused require + uploaded new windows binary + +2006-10-15 21:56 Kent Sibilev + + * ext/ruby_debug.c: Debugger.start yields to the block even if it's + already started + +2006-10-15 19:02 Kent Sibilev + + * lib/ruby-debug/commands/display.rb: remove unused constructor + +2006-10-15 18:56 Kent Sibilev + + * CHANGES: ditto + +2006-10-15 16:54 Kent Sibilev + + * ext/ruby_debug.c, lib/ruby-debug.rb, + lib/ruby-debug/commands/threads.rb: new logic of context + suspend/resume + +2006-10-15 07:37 Kent Sibilev + + * CHANGES: ditto + +2006-10-15 07:36 Kent Sibilev + + * bin/rdebug, ext/ruby_debug.c, lib/ruby-debug.rb, + lib/ruby-debug/lock.rb: fixed locking of debugger threads + +2006-10-14 19:11 Kent Sibilev + + * Rakefile, ext/ruby_debug.c: make skip status local to a thread + instead of globally disabling the debugger. + +2006-10-09 22:01 Kent Sibilev + + * ext/ruby_debug.c, ext/win32/ruby_debug.so, + lib/ruby-debug/interface.rb: fixes for windows version + +2006-10-09 19:06 Kent Sibilev + + * CHANGES, ext/ruby_debug.c, lib/ruby-debug.rb, + lib/ruby-debug/interface.rb: added Debugger.skip and + Debugger.debug_at_exit methods + +2006-10-09 16:48 Kent Sibilev + + * .gdb_history, ext/.gdb_history, ext/Makefile, + ext/ruby_debug.bundle: remove intermediate files + +2006-10-09 16:44 Kent Sibilev + + * ., .gdb_history, CHANGES, LICENSE, README, Rakefile, bin, + bin/rdebug, doc, ext, ext/.gdb_history, ext/Makefile, + ext/extconf.rb, ext/ruby_debug.bundle, ext/ruby_debug.c, + ext/win32, ext/win32/ruby_debug.so, lib, lib/ruby-debug, + lib/ruby-debug.rb, lib/ruby-debug/command.rb, + lib/ruby-debug/commands, lib/ruby-debug/commands/breakpoints.rb, + lib/ruby-debug/commands/catchpoint.rb, + lib/ruby-debug/commands/control.rb, + lib/ruby-debug/commands/display.rb, + lib/ruby-debug/commands/eval.rb, + lib/ruby-debug/commands/frame.rb, + lib/ruby-debug/commands/help.rb, lib/ruby-debug/commands/list.rb, + lib/ruby-debug/commands/method.rb, + lib/ruby-debug/commands/script.rb, + lib/ruby-debug/commands/stepping.rb, + lib/ruby-debug/commands/threads.rb, + lib/ruby-debug/commands/tmate.rb, + lib/ruby-debug/commands/trace.rb, + lib/ruby-debug/commands/variables.rb, + lib/ruby-debug/interface.rb, lib/ruby-debug/lock.rb, + lib/ruby-debug/processor.rb: initial import + diff --git a/INSTALL.SVN b/INSTALL.SVN new file mode 100644 index 0000000..2d10b0c --- /dev/null +++ b/INSTALL.SVN @@ -0,0 +1,154 @@ +Building and Installing ruby-debug from rubyforge's Subversion Repository (svn) + +The below are Unix-centric instructions. If you have Microsoft Windows see +the section on building Microsoft Windows. + + +0. Prerequisites: To build the package you'll need at a minimum: + + - Ruby (of course). Currently only version 1.8.6 and above but not + version 1.9.x work. + - Ruby development headers. This typically includes a file called "ruby.h" + - A C compiler like GNU C (gcc) + - Rake + - Subversion (svn) + +If you want to build the documentation and install Emacs files, you'll +also need: + + - a POSIX shell + - autoconf + - automake + - GNU Make + - texinfo + +1. Basic package checkout and installation + +Check out the trunk of repository following the instructions at +http://rubyforge.org/scm/?group_id=1900 For example on a Unixy system, +this may work: + + mkdir ruby-debug + cd ruby-debug + svn checkout svn://rubyforge.org/var/svn/ruby-debug/trunk trunk + +In order to make the Ruby gems, ruby-debug and ruby-debug-base, get +yourself into the trunk directory after the code has been checked out and run: + + cd trunk # This is the same trunk checked out above. + rake package + +If all goes well you should have some gem files put in the directory +pkg. Use the gem command to install that. + + sudo gem install ruby-debug-*.gem # See gem help for other possibilities + +If all goes well the rdebug script has been installed ruby-debug is +now ready to run. But if everything goes well you might want to run +the built-in regression tests to make sure everything is okay. +See step 3 below. + +If the gem install didn't work,'t there may be a problem with your C +compiler or the Ruby headers are not installed. + +2. Trying out without installing. + +You don't have to build a gem file to try out ruby debug. In fact when +developing new features for ruby-debug, developers often you want to +try it out *before* installing. If you have a problem in the latter +part of step 1 you may want to try this approach since we go into a +little more detail as to what happens under the covers when you do the +gem install. + +Run (from trunk) + rake lib + +This creates a Makefile and builds the ruby-debug shared library. (On +Unix the name is ruby_debug.so). + +Once this is done you can run the debugger as you would rdebug using the +script rdbg.rb. For example (again from trunk) + + ./rdbg.rb ~/my-ruby-program.rb + +3. Running the Regression tests + +We've put together some basic tests to make sure ruby-debug is doing +what we think it should do. To run these (from trunk): + + rake test + +If you didn't build the ruby-debug shared library and skipped step 2, +don't worry "rake test" will do step 2 for you. You should see a line that +ends something like: + + Finished in 2.767579 seconds. + + 12 tests, 35 assertions, 0 failures, 0 errors + +The number of seconds, tests, and assertions may be different from the +above. However you *should* see exactly "0 failures, 0 errors". + +4. Building the documentation and testing/installing Emacs files + +Of course, I recommend you read the ruby-debug manual that comes with +the package. If you have the prerequisites described above, run this +once: + sh ./autogen.sh + +Then run: + ./configure + make + make test # Runs Emacs regression tests + sudo make install # Or arrange to do this as root + + +Microsoft Windows + +A problem here seems to be that the "One-click" install is compiled +using Microsoft Visual Studio C 6 which is not sold anymore and is +rather old. + +Instead I suggest building via mingw/msys. +http://eigenclass.org/hiki.rb?cmd=view&p=cross+compiling+rcovrt&key=mingw has instructions on how to do. Some amendments to these instructions. + +First, those instructions are a little GNU/Linux centric. If you are +using Ubuntu or Debian, then this should be the easiest to follow the +instructions. On Ubuntu or Debian there is a mingw3 Debian +package. Installing that will give you the cross compiler that is a +prerequisite. Alternatively if you are running MS Windows I notice +that cygwin also has a mingw package. Or possibly you could use MinGW +directly. For other OS's you might have to build a cross-compiler, +i.e. gcc which emits win32 code and can create a win32 DLL. + +After you have a cross compiler you need to download the Ruby source +and basically build a ruby interpreter. The cross-compile.sh script +works although when I downloaded it, it had lots of blank space at the +beginning which will mess up the Unix magic interpretation. That is +remove the blanks in front of "#/bin/sh" + +On my system, this script fails in running "make ruby" because the +fake.rb that got created needed to have a small change: + + ALT_SEPARATOR = "\"; \ +should be + ALT_SEPARATOR = "\\"; \ + +After fixing this, run + make ruby +Also, I needed to run + make rubyw + +And then "make install" as indicated. + +Once all of that's in place, the place you want be is in +ruby-debug/trunk/ext/win32, not ruby-debug/ext. + +So let's say you've installed the cross-compiled install ruby in +/usr/local/ruby-mingw32/. Here then are the commands to build ruby-debug-base-xxx-mswin32.gem + + cd .../ruby-debug/trunk/ext/win32 + ruby -I /usr/local/ruby-mingw32/lib/ruby/1.8/i386-mingw32 ../extconf.rb + make # Not rake + cd ../.. # back in ruby-debug/trunk + rake win32_gem diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c5b3b3c --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Copyright (C) 2005 Kent Sibilev +All rights reserved. + * +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. \ No newline at end of file diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..d192367 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,14 @@ +SUBDIRS = doc emacs +PHONY = test ChangeLogs +test: check +ChangeLogs: ChangeLog doc/ChangeLog emacs/ChangeLog lib/ChangeLog +ChangeLog: + svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk \ + cli test bin AUTHORS CHANGES LICENSE README runner.sh -o ChangeLog +lib/ChangeLog: + svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk \ + lib ext -o lib/ChangeLog +doc/ChangeLog: + svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk/doc -o doc/ChangeLog +emacs/ChangeLog: + svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk/emacs -o emacs/ChangeLog diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..46dd0ea --- /dev/null +++ b/Rakefile @@ -0,0 +1,255 @@ +#!/usr/bin/env rake +# -*- Ruby -*- +require 'rubygems' +require 'rake/gempackagetask' +require 'rake/rdoctask' +require 'rake/testtask' + +SO_NAME = "ruby_debug.so" + +# ------- Default Package ---------- +RUBY_DEBUG_VERSION = open("ext/ruby_debug.c") do |f| + f.grep(/^#define DEBUG_VERSION/).first[/"(.+)"/,1] +end + +COMMON_FILES = FileList[ + 'AUTHORS', + 'CHANGES', + 'LICENSE', + 'README', + 'Rakefile', +] + +CLI_TEST_FILE_LIST = FileList['test/cli/commands/unit/*.rb', + 'test/cli/commands/*_test.rb', + 'test/cli/**/*_test.rb', + 'test/test-*.rb'] +CLI_FILES = COMMON_FILES + FileList[ + "cli/**/*", + 'ChangeLog', + 'bin/*', + 'doc/rdebug.1', + 'test/**/data/*.cmd', + 'test/**/data/*.right', + 'test/**/*.rb', + 'rdbg.rb', + CLI_TEST_FILE_LIST +] + +BASE_TEST_FILE_LIST = %w( + test/base/base.rb + test/base/binding.rb + test/base/catchpoint.rb) +BASE_FILES = COMMON_FILES + FileList[ + 'ext/breakpoint.c', + 'ext/extconf.rb', + 'ext/ruby_debug.c', + 'ext/ruby_debug.h', + 'ext/win32/*', + 'lib/**/*', + BASE_TEST_FILE_LIST, +] + +desc "Test everything." +task :test => :test_base do + Rake::TestTask.new(:test) do |t| + t.libs << ['./ext', './lib', './cli'] + t.test_files = CLI_TEST_FILE_LIST + t.verbose = true + end +end + +desc "Test ruby-debug-base." +task :test_base => :lib do + Rake::TestTask.new(:test_base) do |t| + t.libs << ['./ext', './lib'] + t.test_files = FileList[BASE_TEST_FILE_LIST] + t.verbose = true + end +end + +desc "Test everything - same as test." +task :check => :test + +desc "Create the core ruby-debug shared library extension" +task :lib do + Dir.chdir("ext") do + system("#{Gem.ruby} extconf.rb && make") + end +end + +desc "Compile Emacs code" +task :emacs => "emacs/rdebug.elc" +file "emacs/rdebug.elc" => ["emacs/elisp-comp", "emacs/rdebug.el"] do + Dir.chdir("emacs") do + system("./elisp-comp ./rdebug.el") + end +end + +desc "Create a GNU-style ChangeLog via svn2cl" +task :ChangeLog do + system("svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk") + system("svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk/ext -o ext/ChangeLog") + system("svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk/lib -o lib/ChangeLog") +end + +# Base GEM Specification +base_spec = Gem::Specification.new do |spec| + spec.name = "ruby-debug-base" + + spec.homepage = "http://rubyforge.org/projects/ruby-debug/" + spec.summary = "Fast Ruby debugger - core component" + spec.description = <<-EOF +ruby-debug is a fast implementation of the standard Ruby debugger debug.rb. +It is implemented by utilizing a new Ruby C API hook. The core component +provides support that front-ends can build on. It provides breakpoint +handling, bindings for stack frames among other things. +EOF + + spec.version = RUBY_DEBUG_VERSION + + spec.author = "Kent Sibilev" + spec.email = "ksibilev@yahoo.com" + spec.platform = Gem::Platform::RUBY + spec.require_path = "lib" + spec.extensions = ["ext/extconf.rb"] + spec.files = BASE_FILES.to_a + + spec.required_ruby_version = '>= 1.8.2' + spec.date = Time.now + spec.rubyforge_project = 'ruby-debug' + spec.add_dependency('linecache', '>= 0.3') + + spec.test_files = FileList[BASE_TEST_FILE_LIST] + + # rdoc + spec.has_rdoc = true + spec.extra_rdoc_files = ['README', 'ext/ruby_debug.c'] +end + +cli_spec = Gem::Specification.new do |spec| + spec.name = "ruby-debug" + + spec.homepage = "http://rubyforge.org/projects/ruby-debug/" + spec.summary = "Command line interface (CLI) for ruby-debug-base" + spec.description = <<-EOF +A generic command line interface for ruby-debug. +EOF + + spec.version = RUBY_DEBUG_VERSION + + spec.author = "Kent Sibilev" + spec.email = "ksibilev@yahoo.com" + spec.platform = Gem::Platform::RUBY + spec.require_path = "cli" + spec.bindir = "bin" + spec.executables = ["rdebug"] + spec.files = CLI_FILES.to_a + + spec.required_ruby_version = '>= 1.8.2' + spec.date = Time.now + spec.rubyforge_project = 'ruby-debug' + spec.add_dependency('columnize', '>= 0.1') + spec.add_dependency('ruby-debug-base', "~> #{RUBY_DEBUG_VERSION}.0") + + # FIXME: work out operational logistics for this + # spec.test_files = FileList[CLI_TEST_FILE_LIST] + + # rdoc + spec.has_rdoc = true + spec.extra_rdoc_files = ['README'] +end + +# Rake task to build the default package +Rake::GemPackageTask.new(base_spec) do |pkg| + pkg.need_tar = true +end +Rake::GemPackageTask.new(cli_spec) do |pkg| + pkg.need_tar = true +end + +task :default => [:package] + +# Windows specification +win_spec = base_spec.clone +win_spec.extensions = [] +## win_spec.platform = Gem::Platform::WIN32 # deprecated +win_spec.platform = 'mswin32' +win_spec.files += ["lib/#{SO_NAME}"] + +desc "Create Windows Gem" +task :win32_gem do + # Copy the win32 extension the top level directory + current_dir = File.expand_path(File.dirname(__FILE__)) + source = File.join(current_dir, "ext", "win32", SO_NAME) + target = File.join(current_dir, "lib", SO_NAME) + cp(source, target) + + # Create the gem, then move it to pkg. + Gem::Builder.new(win_spec).build + gem_file = "#{win_spec.name}-#{win_spec.version}-#{win_spec.platform}.gem" + mv(gem_file, "pkg/#{gem_file}") + + # Remove win extension from top level directory. + rm(target) +end + +desc "Publish ruby-debug to RubyForge." +task :publish do + require 'rake/contrib/sshpublisher' + + # Get ruby-debug path. + ruby_debug_path = File.expand_path(File.dirname(__FILE__)) + + Rake::SshDirPublisher.new("kent@rubyforge.org", + "/var/www/gforge-projects/ruby-debug", ruby_debug_path) +end + +desc "Remove built files" +task :clean do + cd "ext" do + if File.exists?("Makefile") + sh "make clean" + rm "Makefile" + end + derived_files = Dir.glob(".o") + Dir.glob("*.so") + rm derived_files unless derived_files.empty? + end +end + +# --------- RDoc Documentation ------ +desc "Generate rdoc documentation" +Rake::RDocTask.new("rdoc") do |rdoc| + rdoc.rdoc_dir = 'doc/rdoc' + rdoc.title = "ruby-debug" + # Show source inline with line numbers + rdoc.options << "--inline-source" << "--line-numbers" + # Make the readme file the start page for the generated html + rdoc.options << '--main' << 'README' + rdoc.rdoc_files.include('bin/**/*', + 'cli/ruby-debug/commands/*.rb', + 'lib/**/*.rb', + 'ext/**/ruby_debug.c', + 'README', + 'LICENSE') +end + +desc "Publish the release files to RubyForge." +task :rubyforge_upload do + `rubyforge login` + release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} '#{PKG_NAME}-#{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.gem" + puts release_command + system(release_command) +end + +PKG_NAME = 'ruby-debug' +desc "Publish the release files to RubyForge." +task :rubyforge_upload do + `rubyforge login` + for pkg_name in ['ruby-debug', 'ruby-debug-base'] do + pkg_file_name = "#{pkg_name}-#{pkg_version}" + release_command = "rubyforge add_release ruby-debug #{pkg_name} '#{pkg_file_name}' pkg/#{pkg_file_name}.gem" + puts release_command + system(release_command) + end +end diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..2176ebc --- /dev/null +++ b/autogen.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# Things to do after doing a clean SVN update to add the proper files. +ln -vfs CHANGES NEWS +autoreconf -i -s diff --git a/bin/.svn/README.txt b/bin/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/bin/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/bin/.svn/empty-file b/bin/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/bin/.svn/entries b/bin/.svn/entries new file mode 100644 index 0000000..6cc6464 --- /dev/null +++ b/bin/.svn/entries @@ -0,0 +1,22 @@ + + + + + diff --git a/bin/.svn/format b/bin/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/bin/.svn/format @@ -0,0 +1 @@ +4 diff --git a/bin/.svn/prop-base/rdebug.svn-base b/bin/.svn/prop-base/rdebug.svn-base new file mode 100644 index 0000000..a669705 --- /dev/null +++ b/bin/.svn/prop-base/rdebug.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 0 + +END diff --git a/bin/.svn/props/rdebug.svn-work b/bin/.svn/props/rdebug.svn-work new file mode 100644 index 0000000..a669705 --- /dev/null +++ b/bin/.svn/props/rdebug.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 0 + +END diff --git a/bin/.svn/text-base/rdebug.svn-base b/bin/.svn/text-base/rdebug.svn-base new file mode 100644 index 0000000..4866fc5 --- /dev/null +++ b/bin/.svn/text-base/rdebug.svn-base @@ -0,0 +1,415 @@ +#!/usr/bin/env ruby + +#=== Summary +# +#A command-line front-end to the Ruby debugger, ruby-debug, the +#Fast Ruby Debugger. +# +#Command invocation: +# +# rdebug [options] [--] [script-options] ruby-script-to-debug +# rdebug [options] [script-options] [--client] +# rdebug [--version | --help] +# +#=== Options +# +#-A | --annotate level:: +# Set gdb-style annotation to level, a number. Additional +# information is output automatically when program state is +# changed. This can be used by front-ends such as GNU Emacs to post +# this updated information without having to poll for it. +# +#--client:: +# Connect to a remote debugger. Used with another rdebug invocation +# using --server. See also --host and +# --cport options +# +#--cport=port:: +# Use port port for access to debugger control. +# +#-d | --debug:: +# Set $DEBUG true. +# +#--emacs:: +# Activates full GNU Emacs mode. Is the equivalent of setting the +# options --emacs-basic --annotate=3 --no-stop --no-control +# --post-mortem. +# +#--emacs-basic:: +# Activates GNU Emacs mode. Debugger prompts are prefaced with two +# octal 032 characters. +# +#-h | --host=host:: +# Use host name host for remote debugging. +# +#-I | --include path +# Add path to $LOAD_PATH +# +#-m | --post-mortem:: +# Activate post-mortem mode. +# +#--no-control:: +# Do not automatically start control thread. +# +#--no-stop:: +# Do not stop when script is loaded. +# +#-p | --port=PORT:: +# Host name used for remote debugging. +# +#-r | --requirescript:: +# Require the library, before executing your script. +# +#--script file:: +# Run debugger script file file +# +#-x | --trace:: +# Show lines before executing them. +# +#--no-quit:: +# Do not quit when script terminates. Instead rerun the +# program. +# +#--version:: +# Show the version number and exit. +# +#--verbose:: +# Turn on verbose mode. +# +#--v:: +# Print the version number, then turn on verbose mode if +# a script name is given. If no script name is given +# just exit after printing the version number. +# +#--nx:: +# Don’t execute commands found in any initialization +# files, e.g. .rdebugrc. +# +#--keep-frame-binding:: +# Keep frame bindings. +# +#--script=file:: +# Name of the script file to run +# +#-s | --server:: +# Listen for remote connections. Another rdebug session +# accesses using the --client option. See also the +# --host, --port and --cport options +# +#-w | --wait:: +# Wait for a client connection; implies -s option. +# +#--help:: +# Show invocation help and exit. + +require 'rubygems' +require 'optparse' +require 'ostruct' +require 'ruby-debug' + +def debug_program(options) + # Make sure Ruby script syntax checks okay. + # Otherwise we get a load message that looks like rdebug has + # a problem. + output = `ruby -c "#{Debugger::PROG_SCRIPT}" 2>&1` + if $?.exitstatus != 0 and RUBY_PLATFORM !~ /mswin/ + puts output + exit $?.exitstatus + end + print "\032\032starting\n" if Debugger.annotate and Debugger.annotate > 2 + + # Record where we are we can know if the call stack has been + # truncated or not. + Debugger.start_sentinal=caller(0)[1] + + bt = Debugger.debug_load(Debugger::PROG_SCRIPT, options.stop, false) + if bt + if options.post_mortem + Debugger.handle_post_mortem(bt) + else + print bt.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n" + print "Uncaught exception: #{bt}\n" + end + end +end + +# Do a shell-like path lookup for prog_script and return the results. +# If we can't find anything return prog_script. +def whence_file(prog_script) + if prog_script.index(File::SEPARATOR) + # Don't search since this name has path separator components + return prog_script + end + for dirname in ENV['PATH'].split(File::PATH_SEPARATOR) do + prog_script_try = File.join(dirname, prog_script) + return prog_script_try if File.exist?(prog_script_try) + end + # Failure + return prog_script +end + +options = OpenStruct.new( + 'annotate' => Debugger.annotate, + 'client' => false, + 'control' => true, + 'cport' => Debugger::PORT + 1, + 'frame_bind' => false, + 'host' => nil, + 'quit' => true, + 'no_rewrite_program' => false, + 'stop' => true, + 'nx' => false, + 'port' => Debugger::PORT, + 'post_mortem' => false, + 'restart_script' => nil, + 'script' => nil, + 'server' => false, + 'tracing' => false, + 'verbose_long' => false, + 'wait' => false +) + +def process_options(options) + program = File.basename($0) + opts = OptionParser.new do |opts| + opts.banner = < -- +EOB + opts.separator "" + opts.separator "Options:" + opts.on("-A", "--annotate LEVEL", Integer, "Set annotation level") do + |annotate| + Debugger.annotate = annotate + end + opts.on("-c", "--client", "Connect to remote debugger") do + options.client = true + end + opts.on("--cport PORT", Integer, "Port used for control commands") do + |cport| + options.cport = cport + end + opts.on("-d", "--debug", "Set $DEBUG=true") {$DEBUG = true} + opts.on("--emacs LEVEL", Integer, + "Activates full Emacs support at annotation level LEVEL") do + |level| + Debugger.annotate = level.to_i + ENV['EMACS'] = '1' + ENV['COLUMNS'] = '120' if ENV['COLUMNS'].to_i < 120 + options.control = false + options.quit = false + options.post_mortem = true + end + opts.on('--emacs-basic', 'Activates basic Emacs mode') do + ENV['EMACS'] = '1' + end + opts.on('-h', '--host HOST', 'Host name used for remote debugging') do + |host| + options.host = host + end + opts.on('-I', '--include PATH', String, 'Add PATH to $LOAD_PATH') do |path| + $LOAD_PATH.unshift(path) + end + opts.on('--keep-frame-binding', 'Keep frame bindings') do + options.frame_bind = true + end + opts.on('-m', '--post-mortem', 'Activate post-mortem mode') do + options.post_mortem = true + end + opts.on('--no-control', 'Do not automatically start control thread') do + options.control = false + end + opts.on('--no-quit', 'Do not quit when script finishes') do + options.quit = false + end + opts.on('--no-rewrite-program', + 'Do not set $0 to the program being debugged') do + options.no_rewrite_program = true + end + opts.on('--no-stop', 'Do not stop when script is loaded') do + options.stop = false + end + opts.on('-nx', 'Not run debugger initialization files (e.g. .rdebugrc') do + options.nx = true + end + opts.on('-p', '--port PORT', Integer, 'Port used for remote debugging') do + |port| + options.port = port + end + opts.on('-r', '--require SCRIPT', String, + 'Require the library, before executing your script') do |name| + if name == 'debug' + puts "ruby-debug is not compatible with Ruby's 'debug' library. This option is ignored." + else + require name + end + end + opts.on('--restart-script FILE', String, + 'Name of the script file to run. Erased after read') do + |restart_script| + options.restart_script = restart_script + unless File.exists?(options.restart_script) + puts "Script file '#{options.restart_script}' is not found" + exit + end + end + opts.on('--script FILE', String, 'Name of the script file to run') do + |script| + options.script = script + unless File.exists?(options.script) + puts "Script file '#{options.script}' is not found" + exit + end + end + opts.on('-s', '--server', 'Listen for remote connections') do + options.server = true + end + opts.on('-w', '--wait', 'Wait for a client connection, implies -s option') do + options.wait = true + end + opts.on('-x', '--trace', 'Turn on line tracing') {options.tracing = true} + opts.separator '' + opts.separator 'Common options:' + opts.on_tail('--help', 'Show this message') do + puts opts + exit + end + opts.on_tail('--version', + 'Print the version') do + puts "ruby-debug #{Debugger::VERSION}" + exit + end + opts.on('--verbose', 'Turn on verbose mode') do + $VERBOSE = true + options.verbose_long = true + end + opts.on_tail('-v', + 'Print version number, then turn on verbose mode') do + puts "ruby-debug #{Debugger::VERSION}" + $VERBOSE = true + end + end + return opts +end + +# What file is used for debugger startup commands. +unless defined?(OPTS_INITFILE) + if RUBY_PLATFORM =~ /mswin/ + # Of course MS Windows has to be different + OPTS_INITFILE = 'rdbopt.ini' + HOME_DIR = (ENV['HOME'] || + ENV['HOMEDRIVE'].to_s + ENV['HOMEPATH'].to_s).to_s + else + OPTS_INITFILE = '.rdboptrc' + HOME_DIR = ENV['HOME'].to_s + end +end +begin + initfile = File.join(HOME_DIR, OPTS_INITFILE) + eval(File.read(initfile)) if + File.exist?(initfile) +rescue +end + +opts = process_options(options) +begin + if not defined? Debugger::ARGV + Debugger::ARGV = ARGV.clone + end + rdebug_path = File.expand_path($0) + if RUBY_PLATFORM =~ /mswin/ + rdebug_path += '.cmd' unless rdebug_path =~ /\.cmd$/i + end + Debugger::RDEBUG_SCRIPT = rdebug_path + Debugger::RDEBUG_FILE = __FILE__ + Debugger::INITIAL_DIR = Dir.pwd + opts.parse! ARGV +rescue StandardError => e + puts opts + puts + puts e.message + exit(-1) +end + +if options.client + Debugger.start_client(options.host, options.port) +else + if ARGV.empty? + exit if $VERBOSE and not options.verbose_long + puts opts + puts + puts 'Must specify a script to run' + exit(-1) + end + + # save script name + prog_script = ARGV.shift + prog_script = whence_file(prog_script) unless File.exist?(prog_script) + Debugger::PROG_SCRIPT = File.expand_path prog_script + + # install interruption handler + trap('INT') { Debugger.interrupt_last } + + # set options + Debugger.wait_connection = options.wait + Debugger.keep_frame_binding = options.frame_bind + + if options.server + # start remote mode + Debugger.start_remote(options.host, [options.port, options.cport], + options.post_mortem) do + # load initrc script + Debugger.run_init_script(StringIO.new) unless options.nx + end + debug_program(options) + else + # Set up trace hook for debugger + Debugger.start + # start control thread + Debugger.start_control(options.host, options.cport) if options.control + + # load initrc script (e.g. .rdebugrc) + Debugger.run_init_script(StringIO.new) unless options.nx + + # run restore-settings startup script if specified + if options.restart_script + require 'fileutils' + Debugger.run_script(options.restart_script) + FileUtils.rm(options.restart_script) + end + + # run startup script if specified + if options.script + Debugger.run_script(options.script) + end + + # activate post-mortem + Debugger.post_mortem if options.post_mortem + options.stop = false if options.tracing + Debugger.tracing = options.tracing + + if !options.quit + if Debugger.started? + until Debugger.stop do end + end + begin + debug_program(options) + rescue SyntaxError + puts $!.backtrace.map{|l| "\t#{l}"}.join("\n") + puts "Uncaught Syntax Error\n" + rescue + print $!.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n" + print "Uncaught exception: #{$!}\n" + end + print "The program finished.\n" unless + Debugger.annotate.to_i > 1 # annotate has its own way + interface = Debugger::LocalInterface.new + # Not sure if ControlCommandProcessor is really the right + # thing to use. CommandProcessor requires a state. + processor = Debugger::ControlCommandProcessor.new(interface) + processor.process_commands + else + debug_program(options) + end + end +end diff --git a/bin/rdebug b/bin/rdebug new file mode 100755 index 0000000..4866fc5 --- /dev/null +++ b/bin/rdebug @@ -0,0 +1,415 @@ +#!/usr/bin/env ruby + +#=== Summary +# +#A command-line front-end to the Ruby debugger, ruby-debug, the +#Fast Ruby Debugger. +# +#Command invocation: +# +# rdebug [options] [--] [script-options] ruby-script-to-debug +# rdebug [options] [script-options] [--client] +# rdebug [--version | --help] +# +#=== Options +# +#-A | --annotate level:: +# Set gdb-style annotation to level, a number. Additional +# information is output automatically when program state is +# changed. This can be used by front-ends such as GNU Emacs to post +# this updated information without having to poll for it. +# +#--client:: +# Connect to a remote debugger. Used with another rdebug invocation +# using --server. See also --host and +# --cport options +# +#--cport=port:: +# Use port port for access to debugger control. +# +#-d | --debug:: +# Set $DEBUG true. +# +#--emacs:: +# Activates full GNU Emacs mode. Is the equivalent of setting the +# options --emacs-basic --annotate=3 --no-stop --no-control +# --post-mortem. +# +#--emacs-basic:: +# Activates GNU Emacs mode. Debugger prompts are prefaced with two +# octal 032 characters. +# +#-h | --host=host:: +# Use host name host for remote debugging. +# +#-I | --include path +# Add path to $LOAD_PATH +# +#-m | --post-mortem:: +# Activate post-mortem mode. +# +#--no-control:: +# Do not automatically start control thread. +# +#--no-stop:: +# Do not stop when script is loaded. +# +#-p | --port=PORT:: +# Host name used for remote debugging. +# +#-r | --requirescript:: +# Require the library, before executing your script. +# +#--script file:: +# Run debugger script file file +# +#-x | --trace:: +# Show lines before executing them. +# +#--no-quit:: +# Do not quit when script terminates. Instead rerun the +# program. +# +#--version:: +# Show the version number and exit. +# +#--verbose:: +# Turn on verbose mode. +# +#--v:: +# Print the version number, then turn on verbose mode if +# a script name is given. If no script name is given +# just exit after printing the version number. +# +#--nx:: +# Don’t execute commands found in any initialization +# files, e.g. .rdebugrc. +# +#--keep-frame-binding:: +# Keep frame bindings. +# +#--script=file:: +# Name of the script file to run +# +#-s | --server:: +# Listen for remote connections. Another rdebug session +# accesses using the --client option. See also the +# --host, --port and --cport options +# +#-w | --wait:: +# Wait for a client connection; implies -s option. +# +#--help:: +# Show invocation help and exit. + +require 'rubygems' +require 'optparse' +require 'ostruct' +require 'ruby-debug' + +def debug_program(options) + # Make sure Ruby script syntax checks okay. + # Otherwise we get a load message that looks like rdebug has + # a problem. + output = `ruby -c "#{Debugger::PROG_SCRIPT}" 2>&1` + if $?.exitstatus != 0 and RUBY_PLATFORM !~ /mswin/ + puts output + exit $?.exitstatus + end + print "\032\032starting\n" if Debugger.annotate and Debugger.annotate > 2 + + # Record where we are we can know if the call stack has been + # truncated or not. + Debugger.start_sentinal=caller(0)[1] + + bt = Debugger.debug_load(Debugger::PROG_SCRIPT, options.stop, false) + if bt + if options.post_mortem + Debugger.handle_post_mortem(bt) + else + print bt.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n" + print "Uncaught exception: #{bt}\n" + end + end +end + +# Do a shell-like path lookup for prog_script and return the results. +# If we can't find anything return prog_script. +def whence_file(prog_script) + if prog_script.index(File::SEPARATOR) + # Don't search since this name has path separator components + return prog_script + end + for dirname in ENV['PATH'].split(File::PATH_SEPARATOR) do + prog_script_try = File.join(dirname, prog_script) + return prog_script_try if File.exist?(prog_script_try) + end + # Failure + return prog_script +end + +options = OpenStruct.new( + 'annotate' => Debugger.annotate, + 'client' => false, + 'control' => true, + 'cport' => Debugger::PORT + 1, + 'frame_bind' => false, + 'host' => nil, + 'quit' => true, + 'no_rewrite_program' => false, + 'stop' => true, + 'nx' => false, + 'port' => Debugger::PORT, + 'post_mortem' => false, + 'restart_script' => nil, + 'script' => nil, + 'server' => false, + 'tracing' => false, + 'verbose_long' => false, + 'wait' => false +) + +def process_options(options) + program = File.basename($0) + opts = OptionParser.new do |opts| + opts.banner = < -- +EOB + opts.separator "" + opts.separator "Options:" + opts.on("-A", "--annotate LEVEL", Integer, "Set annotation level") do + |annotate| + Debugger.annotate = annotate + end + opts.on("-c", "--client", "Connect to remote debugger") do + options.client = true + end + opts.on("--cport PORT", Integer, "Port used for control commands") do + |cport| + options.cport = cport + end + opts.on("-d", "--debug", "Set $DEBUG=true") {$DEBUG = true} + opts.on("--emacs LEVEL", Integer, + "Activates full Emacs support at annotation level LEVEL") do + |level| + Debugger.annotate = level.to_i + ENV['EMACS'] = '1' + ENV['COLUMNS'] = '120' if ENV['COLUMNS'].to_i < 120 + options.control = false + options.quit = false + options.post_mortem = true + end + opts.on('--emacs-basic', 'Activates basic Emacs mode') do + ENV['EMACS'] = '1' + end + opts.on('-h', '--host HOST', 'Host name used for remote debugging') do + |host| + options.host = host + end + opts.on('-I', '--include PATH', String, 'Add PATH to $LOAD_PATH') do |path| + $LOAD_PATH.unshift(path) + end + opts.on('--keep-frame-binding', 'Keep frame bindings') do + options.frame_bind = true + end + opts.on('-m', '--post-mortem', 'Activate post-mortem mode') do + options.post_mortem = true + end + opts.on('--no-control', 'Do not automatically start control thread') do + options.control = false + end + opts.on('--no-quit', 'Do not quit when script finishes') do + options.quit = false + end + opts.on('--no-rewrite-program', + 'Do not set $0 to the program being debugged') do + options.no_rewrite_program = true + end + opts.on('--no-stop', 'Do not stop when script is loaded') do + options.stop = false + end + opts.on('-nx', 'Not run debugger initialization files (e.g. .rdebugrc') do + options.nx = true + end + opts.on('-p', '--port PORT', Integer, 'Port used for remote debugging') do + |port| + options.port = port + end + opts.on('-r', '--require SCRIPT', String, + 'Require the library, before executing your script') do |name| + if name == 'debug' + puts "ruby-debug is not compatible with Ruby's 'debug' library. This option is ignored." + else + require name + end + end + opts.on('--restart-script FILE', String, + 'Name of the script file to run. Erased after read') do + |restart_script| + options.restart_script = restart_script + unless File.exists?(options.restart_script) + puts "Script file '#{options.restart_script}' is not found" + exit + end + end + opts.on('--script FILE', String, 'Name of the script file to run') do + |script| + options.script = script + unless File.exists?(options.script) + puts "Script file '#{options.script}' is not found" + exit + end + end + opts.on('-s', '--server', 'Listen for remote connections') do + options.server = true + end + opts.on('-w', '--wait', 'Wait for a client connection, implies -s option') do + options.wait = true + end + opts.on('-x', '--trace', 'Turn on line tracing') {options.tracing = true} + opts.separator '' + opts.separator 'Common options:' + opts.on_tail('--help', 'Show this message') do + puts opts + exit + end + opts.on_tail('--version', + 'Print the version') do + puts "ruby-debug #{Debugger::VERSION}" + exit + end + opts.on('--verbose', 'Turn on verbose mode') do + $VERBOSE = true + options.verbose_long = true + end + opts.on_tail('-v', + 'Print version number, then turn on verbose mode') do + puts "ruby-debug #{Debugger::VERSION}" + $VERBOSE = true + end + end + return opts +end + +# What file is used for debugger startup commands. +unless defined?(OPTS_INITFILE) + if RUBY_PLATFORM =~ /mswin/ + # Of course MS Windows has to be different + OPTS_INITFILE = 'rdbopt.ini' + HOME_DIR = (ENV['HOME'] || + ENV['HOMEDRIVE'].to_s + ENV['HOMEPATH'].to_s).to_s + else + OPTS_INITFILE = '.rdboptrc' + HOME_DIR = ENV['HOME'].to_s + end +end +begin + initfile = File.join(HOME_DIR, OPTS_INITFILE) + eval(File.read(initfile)) if + File.exist?(initfile) +rescue +end + +opts = process_options(options) +begin + if not defined? Debugger::ARGV + Debugger::ARGV = ARGV.clone + end + rdebug_path = File.expand_path($0) + if RUBY_PLATFORM =~ /mswin/ + rdebug_path += '.cmd' unless rdebug_path =~ /\.cmd$/i + end + Debugger::RDEBUG_SCRIPT = rdebug_path + Debugger::RDEBUG_FILE = __FILE__ + Debugger::INITIAL_DIR = Dir.pwd + opts.parse! ARGV +rescue StandardError => e + puts opts + puts + puts e.message + exit(-1) +end + +if options.client + Debugger.start_client(options.host, options.port) +else + if ARGV.empty? + exit if $VERBOSE and not options.verbose_long + puts opts + puts + puts 'Must specify a script to run' + exit(-1) + end + + # save script name + prog_script = ARGV.shift + prog_script = whence_file(prog_script) unless File.exist?(prog_script) + Debugger::PROG_SCRIPT = File.expand_path prog_script + + # install interruption handler + trap('INT') { Debugger.interrupt_last } + + # set options + Debugger.wait_connection = options.wait + Debugger.keep_frame_binding = options.frame_bind + + if options.server + # start remote mode + Debugger.start_remote(options.host, [options.port, options.cport], + options.post_mortem) do + # load initrc script + Debugger.run_init_script(StringIO.new) unless options.nx + end + debug_program(options) + else + # Set up trace hook for debugger + Debugger.start + # start control thread + Debugger.start_control(options.host, options.cport) if options.control + + # load initrc script (e.g. .rdebugrc) + Debugger.run_init_script(StringIO.new) unless options.nx + + # run restore-settings startup script if specified + if options.restart_script + require 'fileutils' + Debugger.run_script(options.restart_script) + FileUtils.rm(options.restart_script) + end + + # run startup script if specified + if options.script + Debugger.run_script(options.script) + end + + # activate post-mortem + Debugger.post_mortem if options.post_mortem + options.stop = false if options.tracing + Debugger.tracing = options.tracing + + if !options.quit + if Debugger.started? + until Debugger.stop do end + end + begin + debug_program(options) + rescue SyntaxError + puts $!.backtrace.map{|l| "\t#{l}"}.join("\n") + puts "Uncaught Syntax Error\n" + rescue + print $!.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n" + print "Uncaught exception: #{$!}\n" + end + print "The program finished.\n" unless + Debugger.annotate.to_i > 1 # annotate has its own way + interface = Debugger::LocalInterface.new + # Not sure if ControlCommandProcessor is really the right + # thing to use. CommandProcessor requires a state. + processor = Debugger::ControlCommandProcessor.new(interface) + processor.process_commands + else + debug_program(options) + end + end +end diff --git a/cli/.svn/README.txt b/cli/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/cli/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/cli/.svn/empty-file b/cli/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/cli/.svn/entries b/cli/.svn/entries new file mode 100644 index 0000000..4a42d69 --- /dev/null +++ b/cli/.svn/entries @@ -0,0 +1,25 @@ + + + + + + diff --git a/cli/.svn/format b/cli/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/cli/.svn/format @@ -0,0 +1 @@ +4 diff --git a/cli/.svn/prop-base/ruby-debug.rb.svn-base b/cli/.svn/prop-base/ruby-debug.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/.svn/prop-base/ruby-debug.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/.svn/props/ruby-debug.rb.svn-work b/cli/.svn/props/ruby-debug.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/.svn/props/ruby-debug.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/.svn/text-base/ruby-debug.rb.svn-base b/cli/.svn/text-base/ruby-debug.rb.svn-base new file mode 100644 index 0000000..2c4e6bf --- /dev/null +++ b/cli/.svn/text-base/ruby-debug.rb.svn-base @@ -0,0 +1,176 @@ +require 'pp' +require 'stringio' +require 'socket' +require 'thread' +require 'ruby-debug-base' +require 'ruby-debug/processor' + +module Debugger + self.handler = CommandProcessor.new + + # the port number used for remote debugging + PORT = 8989 unless defined?(PORT) + + # What file is used for debugger startup commands. + unless defined?(INITFILE) + if RUBY_PLATFORM =~ /mswin/ + # Of course MS Windows has to be different + INITFILE = 'rdebug.ini' + HOME_DIR = (ENV['HOME'] || + ENV['HOMEDRIVE'].to_s + ENV['HOMEPATH'].to_s).to_s + else + INITFILE = '.rdebugrc' + HOME_DIR = ENV['HOME'].to_s + end + end + + class << self + # gdb-style annotation mode. Used in GNU Emacs interface + attr_accessor :annotate + + # in remote mode, wait for the remote connection + attr_accessor :wait_connection + + # If set, a string to look for in caller() and is used to see + # if the call stack is truncated. + attr_accessor :start_sentinal + + attr_reader :thread, :control_thread + + def interface=(value) # :nodoc: + handler.interface = value + end + + # + # Starts a remote debugger. + # + def start_remote(host = nil, port = PORT, post_mortem = false) + return if @thread + return if started? + + self.interface = nil + start + self.post_mortem if post_mortem + + if port.kind_of?(Array) + cmd_port, ctrl_port = port + else + cmd_port, ctrl_port = port, port + 1 + end + + start_control(host, ctrl_port) + + yield if block_given? + + mutex = Mutex.new + proceed = ConditionVariable.new + + @thread = DebugThread.new do + server = TCPServer.new(host, cmd_port) + while (session = server.accept) + self.interface = RemoteInterface.new(session) + if wait_connection + mutex.synchronize do + proceed.signal + end + end + end + end + if wait_connection + mutex.synchronize do + proceed.wait(mutex) + end + end + end + alias start_server start_remote + + def start_control(host = nil, ctrl_port = PORT + 1) # :nodoc: + raise "Debugger is not started" unless started? + return if defined?(@control_thread) && @control_thread + @control_thread = DebugThread.new do + server = TCPServer.new(host, ctrl_port) + while (session = server.accept) + interface = RemoteInterface.new(session) + processor = ControlCommandProcessor.new(interface) + processor.process_commands + end + end + end + + # + # Connects to the remote debugger + # + def start_client(host = 'localhost', port = PORT) + require "socket" + interface = Debugger::LocalInterface.new + socket = TCPSocket.new(host, port) + puts "Connected." + + catch(:exit) do + while (line = socket.gets) + case line + when /^PROMPT (.*)$/ + input = interface.read_command($1) + throw :exit unless input + socket.puts input + when /^CONFIRM (.*)$/ + input = interface.confirm($1) + throw :exit unless input + socket.puts input + else + print line + end + end + end + socket.close + end + + # Runs normal debugger initialization scripts + # Reads and executes the commands from init file (if any) in the + # current working directory. This is only done if the current + # directory is different from your home directory. Thus, you can + # have more than one init file, one generic in your home directory, + # and another, specific to the program you are debugging, in the + # directory where you invoke ruby-debug. + def run_init_script(out = handler.interface) + cwd_script_file = File.expand_path(File.join(".", INITFILE)) + run_script(cwd_script_file, out) if File.exists?(cwd_script_file) + + home_script_file = File.expand_path(File.join(HOME_DIR, INITFILE)) + run_script(home_script_file, out) if File.exists?(home_script_file) and + cwd_script_file != home_script_file + end + + # + # Runs a script file + # + def run_script(file, out = handler.interface, verbose=false) + interface = ScriptInterface.new(File.expand_path(file), out) + processor = ControlCommandProcessor.new(interface) + processor.process_commands(verbose) + end + end +end + +module Kernel + + # Enters the debugger in the current thread after _steps_ line events occur. + # Before entering the debugger startup script is read. + # + # Setting _steps_ to 0 will cause a break in the debugger subroutine + # and not wait for a line event to occur. You will have to go "up 1" + # in order to be back in your debugged program rather than the + # debugger. Settings _steps_ to 0 could be useful you want to stop + # right after the last statement in some scope, because the next + # step will take you out of some scope. + def debugger(steps = 1) + Debugger.start unless Debugger.started? + Debugger.run_init_script(StringIO.new) + if 0 == steps + Debugger.current_context.stop_frame = 0 + else + Debugger.current_context.stop_next = steps + end + end + alias breakpoint debugger unless respond_to?(:breakpoint) +end diff --git a/cli/ruby-debug.rb b/cli/ruby-debug.rb new file mode 100644 index 0000000..2c4e6bf --- /dev/null +++ b/cli/ruby-debug.rb @@ -0,0 +1,176 @@ +require 'pp' +require 'stringio' +require 'socket' +require 'thread' +require 'ruby-debug-base' +require 'ruby-debug/processor' + +module Debugger + self.handler = CommandProcessor.new + + # the port number used for remote debugging + PORT = 8989 unless defined?(PORT) + + # What file is used for debugger startup commands. + unless defined?(INITFILE) + if RUBY_PLATFORM =~ /mswin/ + # Of course MS Windows has to be different + INITFILE = 'rdebug.ini' + HOME_DIR = (ENV['HOME'] || + ENV['HOMEDRIVE'].to_s + ENV['HOMEPATH'].to_s).to_s + else + INITFILE = '.rdebugrc' + HOME_DIR = ENV['HOME'].to_s + end + end + + class << self + # gdb-style annotation mode. Used in GNU Emacs interface + attr_accessor :annotate + + # in remote mode, wait for the remote connection + attr_accessor :wait_connection + + # If set, a string to look for in caller() and is used to see + # if the call stack is truncated. + attr_accessor :start_sentinal + + attr_reader :thread, :control_thread + + def interface=(value) # :nodoc: + handler.interface = value + end + + # + # Starts a remote debugger. + # + def start_remote(host = nil, port = PORT, post_mortem = false) + return if @thread + return if started? + + self.interface = nil + start + self.post_mortem if post_mortem + + if port.kind_of?(Array) + cmd_port, ctrl_port = port + else + cmd_port, ctrl_port = port, port + 1 + end + + start_control(host, ctrl_port) + + yield if block_given? + + mutex = Mutex.new + proceed = ConditionVariable.new + + @thread = DebugThread.new do + server = TCPServer.new(host, cmd_port) + while (session = server.accept) + self.interface = RemoteInterface.new(session) + if wait_connection + mutex.synchronize do + proceed.signal + end + end + end + end + if wait_connection + mutex.synchronize do + proceed.wait(mutex) + end + end + end + alias start_server start_remote + + def start_control(host = nil, ctrl_port = PORT + 1) # :nodoc: + raise "Debugger is not started" unless started? + return if defined?(@control_thread) && @control_thread + @control_thread = DebugThread.new do + server = TCPServer.new(host, ctrl_port) + while (session = server.accept) + interface = RemoteInterface.new(session) + processor = ControlCommandProcessor.new(interface) + processor.process_commands + end + end + end + + # + # Connects to the remote debugger + # + def start_client(host = 'localhost', port = PORT) + require "socket" + interface = Debugger::LocalInterface.new + socket = TCPSocket.new(host, port) + puts "Connected." + + catch(:exit) do + while (line = socket.gets) + case line + when /^PROMPT (.*)$/ + input = interface.read_command($1) + throw :exit unless input + socket.puts input + when /^CONFIRM (.*)$/ + input = interface.confirm($1) + throw :exit unless input + socket.puts input + else + print line + end + end + end + socket.close + end + + # Runs normal debugger initialization scripts + # Reads and executes the commands from init file (if any) in the + # current working directory. This is only done if the current + # directory is different from your home directory. Thus, you can + # have more than one init file, one generic in your home directory, + # and another, specific to the program you are debugging, in the + # directory where you invoke ruby-debug. + def run_init_script(out = handler.interface) + cwd_script_file = File.expand_path(File.join(".", INITFILE)) + run_script(cwd_script_file, out) if File.exists?(cwd_script_file) + + home_script_file = File.expand_path(File.join(HOME_DIR, INITFILE)) + run_script(home_script_file, out) if File.exists?(home_script_file) and + cwd_script_file != home_script_file + end + + # + # Runs a script file + # + def run_script(file, out = handler.interface, verbose=false) + interface = ScriptInterface.new(File.expand_path(file), out) + processor = ControlCommandProcessor.new(interface) + processor.process_commands(verbose) + end + end +end + +module Kernel + + # Enters the debugger in the current thread after _steps_ line events occur. + # Before entering the debugger startup script is read. + # + # Setting _steps_ to 0 will cause a break in the debugger subroutine + # and not wait for a line event to occur. You will have to go "up 1" + # in order to be back in your debugged program rather than the + # debugger. Settings _steps_ to 0 could be useful you want to stop + # right after the last statement in some scope, because the next + # step will take you out of some scope. + def debugger(steps = 1) + Debugger.start unless Debugger.started? + Debugger.run_init_script(StringIO.new) + if 0 == steps + Debugger.current_context.stop_frame = 0 + else + Debugger.current_context.stop_next = steps + end + end + alias breakpoint debugger unless respond_to?(:breakpoint) +end diff --git a/cli/ruby-debug/.svn/README.txt b/cli/ruby-debug/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/cli/ruby-debug/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/cli/ruby-debug/.svn/empty-file b/cli/ruby-debug/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/cli/ruby-debug/.svn/entries b/cli/ruby-debug/.svn/entries new file mode 100644 index 0000000..5436448 --- /dev/null +++ b/cli/ruby-debug/.svn/entries @@ -0,0 +1,61 @@ + + + + + + + + + + diff --git a/cli/ruby-debug/.svn/format b/cli/ruby-debug/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/cli/ruby-debug/.svn/format @@ -0,0 +1 @@ +4 diff --git a/cli/ruby-debug/.svn/prop-base/command.rb.svn-base b/cli/ruby-debug/.svn/prop-base/command.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/prop-base/command.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/prop-base/debugger.rb.svn-base b/cli/ruby-debug/.svn/prop-base/debugger.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/prop-base/debugger.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/prop-base/helper.rb.svn-base b/cli/ruby-debug/.svn/prop-base/helper.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/prop-base/helper.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/prop-base/interface.rb.svn-base b/cli/ruby-debug/.svn/prop-base/interface.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/prop-base/interface.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/prop-base/processor.rb.svn-base b/cli/ruby-debug/.svn/prop-base/processor.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/prop-base/processor.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/props/command.rb.svn-work b/cli/ruby-debug/.svn/props/command.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/props/command.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/props/debugger.rb.svn-work b/cli/ruby-debug/.svn/props/debugger.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/props/debugger.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/props/helper.rb.svn-work b/cli/ruby-debug/.svn/props/helper.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/props/helper.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/props/interface.rb.svn-work b/cli/ruby-debug/.svn/props/interface.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/props/interface.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/props/processor.rb.svn-work b/cli/ruby-debug/.svn/props/processor.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/.svn/props/processor.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/.svn/text-base/command.rb.svn-base b/cli/ruby-debug/.svn/text-base/command.rb.svn-base new file mode 100644 index 0000000..f424db9 --- /dev/null +++ b/cli/ruby-debug/.svn/text-base/command.rb.svn-base @@ -0,0 +1,228 @@ +require 'rubygems' +require 'columnize' +require 'ruby-debug/helper' + +module Debugger + RUBY_DEBUG_DIR = File.expand_path(File.dirname(__FILE__)) unless + defined?(RUBY_DEBUG_DIR) + + class Command # :nodoc: + SubcmdStruct=Struct.new(:name, :min, :short_help, :long_help) unless + defined?(SubcmdStruct) + + include Columnize + + # Find param in subcmds. param id downcased and can be abbreviated + # to the minimum length listed in the subcommands + def find(subcmds, param) + param.downcase! + for try_subcmd in subcmds do + if (param.size >= try_subcmd.min) and + (try_subcmd.name[0..param.size-1] == param) + return try_subcmd + end + end + return nil + end + + class << self + def commands + @commands ||= [] + end + + DEF_OPTIONS = { + :allow_in_control => false, + :allow_in_post_mortem => true, + :event => true, + :always_run => 0, + :unknown => false, + :need_context => false, + } unless defined?(DEF_OPTIONS) + + def inherited(klass) + DEF_OPTIONS.each do |o, v| + klass.options[o] = v if klass.options[o].nil? + end + commands << klass + end + + def load_commands + Dir[File.join(Debugger.const_get(:RUBY_DEBUG_DIR), 'commands', '*')].each do |file| + require file if file =~ /\.rb$/ + end + Debugger.constants.grep(/Functions$/).map { |name| Debugger.const_get(name) }.each do |mod| + include mod + end + end + + def method_missing(meth, *args, &block) + if meth.to_s =~ /^(.+?)=$/ + @options[$1.intern] = args.first + else + if @options.has_key?(meth) + @options[meth] + else + super + end + end + end + + def options + @options ||= {} + end + + def settings_map + @@settings_map ||= {} + end + private :settings_map + + def settings + unless true and defined? @settings and @settings + @settings = Object.new + map = settings_map + c = class << @settings; self end + if c.respond_to?(:funcall) + c.funcall(:define_method, :[]) do |name| + raise "No such setting #{name}" unless map.has_key?(name) + map[name][:getter].call + end + else + c.send(:define_method, :[]) do |name| + raise "No such setting #{name}" unless map.has_key?(name) + map[name][:getter].call + end + end + c = class << @settings; self end + if c.respond_to?(:funcall) + c.funcall(:define_method, :[]=) do |name, value| + raise "No such setting #{name}" unless map.has_key?(name) + map[name][:setter].call(value) + end + else + c.send(:define_method, :[]=) do |name, value| + raise "No such setting #{name}" unless map.has_key?(name) + map[name][:setter].call(value) + end + end + end + @settings + end + + def register_setting_var(name, default) + var_name = "@@#{name}" + class_variable_set(var_name, default) + register_setting_get(name) { class_variable_get(var_name) } + register_setting_set(name) { |value| class_variable_set(var_name, value) } + end + + def register_setting_get(name, &block) + settings_map[name] ||= {} + settings_map[name][:getter] = block + end + + def register_setting_set(name, &block) + settings_map[name] ||= {} + settings_map[name][:setter] = block + end + end + + register_setting_var(:basename, false) # use basename in showing files? + register_setting_var(:callstyle, :last) + register_setting_var(:debuggertesting, false) + register_setting_var(:force_stepping, false) + register_setting_var(:full_path, true) + register_setting_var(:listsize, 10) # number of lines in list command + register_setting_var(:stack_trace_on_error, false) + register_setting_var(:tracing_plus, false) # different linetrace lines? + + # width of line output. Use COLUMNS value if it exists and is + # not too rediculously large. + width = ENV['COLUMNS'].to_i + width = 80 unless width > 10 + register_setting_var(:width, width) + + if not defined? Debugger::ARGV + Debugger::ARGV = ARGV.clone + end + register_setting_var(:argv, Debugger::ARGV) + + def initialize(state) + @state = state + end + + def match(input) + @match = regexp.match(input) + end + + protected + + # FIXME: use delegate? + def errmsg(*args) + @state.errmsg(*args) + end + + def print(*args) + @state.print(*args) + end + + def confirm(msg) + @state.confirm(msg) == 'y' + end + + def debug_eval(str, b = get_binding) + begin + val = eval(str, b) + rescue StandardError, ScriptError => e + if Command.settings[:stack_trace_on_error] + at = eval("caller(1)", b) + print "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '') + for i in at + print "\tfrom %s\n", i + end + else + print "#{e.class} Exception: #{e.message}\n" + end + throw :debug_error + end + end + + def debug_silent_eval(str) + begin + eval(str, get_binding) + rescue StandardError, ScriptError + nil + end + end + + def get_binding + @state.context.frame_binding(@state.frame_pos) + end + + def line_at(file, line) + Debugger.line_at(file, line) + end + + def get_context(thnum) + Debugger.contexts.find{|c| c.thnum == thnum} + end + end + + Command.load_commands + + # Returns setting object. + # Use Debugger.settings[] and Debugger.settings[]= methods to query and set + # debugger settings. These settings are available: + # + # - :autolist - automatically calls 'list' command on breakpoint + # - :autoeval - evaluates input in the current binding if it's not recognized as a debugger command + # - :autoirb - automatically calls 'irb' command on breakpoint + # - :stack_trace_on_error - shows full stack trace if eval command results with an exception + # - :frame_full_path - displays full paths when showing frame stack + # - :frame_class_names - displays method's class name when showing frame stack + # - :reload_source_on_change - makes 'list' command to always display up-to-date source code + # - :force_stepping - stepping command asways move to the new line + # + def self.settings + Command.settings + end +end diff --git a/cli/ruby-debug/.svn/text-base/debugger.rb.svn-base b/cli/ruby-debug/.svn/text-base/debugger.rb.svn-base new file mode 100644 index 0000000..d581c05 --- /dev/null +++ b/cli/ruby-debug/.svn/text-base/debugger.rb.svn-base @@ -0,0 +1,5 @@ +# Module/Package to do the most-common thing: get into the debugger with +# minimal fuss. Compare with: require "debug" +require "ruby-debug" +Debugger.start +debugger \ No newline at end of file diff --git a/cli/ruby-debug/.svn/text-base/helper.rb.svn-base b/cli/ruby-debug/.svn/text-base/helper.rb.svn-base new file mode 100644 index 0000000..f159c3c --- /dev/null +++ b/cli/ruby-debug/.svn/text-base/helper.rb.svn-base @@ -0,0 +1,69 @@ +module Debugger + + module ParseFunctions + Position_regexp = '(?:(\d+)|(.+?)[:.#]([^.:\s]+))' + + # Parse 'str' of command 'cmd' as an integer between + # min and max. If either min or max is nil, that + # value has no bound. + def get_int(str, cmd, min=nil, max=nil, default=1) + return default unless str + begin + int = Integer(str) + if min and int < min + print "%s argument '%s' needs to at least %s.\n" % [cmd, str, min] + return nil + elsif max and int > max + print "%s argument '%s' needs to at most %s.\n" % [cmd, str, max] + return nil + end + return int + rescue + print "%s argument '%s' needs to be a number.\n" % [cmd, str] + return nil + end + end + + # Return true if arg is 'on' or 1 and false arg is 'off' or 0. + # Any other value raises RuntimeError. + def get_onoff(arg, default=nil, print_error=true) + if arg.nil? or arg == '' + if default.nil? + if print_error + print "Expecting 'on', 1, 'off', or 0. Got nothing.\n" + raise RuntimeError + end + return default + end + end + case arg.downcase + when '1', 'on' + return true + when '0', 'off' + return false + else + if print_error + print "Expecting 'on', 1, 'off', or 0. Got: %s.\n" % arg.to_s + raise RuntimeError + end + end + end + + # Return 'on' or 'off' for supplied parameter. The parmeter should + # be true, false or nil. + def show_onoff(bool) + if not [TrueClass, FalseClass, NilClass].member?(bool.class) + return "??" + end + return bool ? 'on' : 'off' + end + + # Return true if code is syntactically correct for Ruby. + def syntax_valid?(code) + eval("BEGIN {return true}\n#{code}", nil, "", 0) + rescue Exception + false + end + + end +end diff --git a/cli/ruby-debug/.svn/text-base/interface.rb.svn-base b/cli/ruby-debug/.svn/text-base/interface.rb.svn-base new file mode 100644 index 0000000..63feea1 --- /dev/null +++ b/cli/ruby-debug/.svn/text-base/interface.rb.svn-base @@ -0,0 +1,232 @@ +module Debugger + class Interface # :nodoc: + attr_writer :have_readline # true if Readline is available + + def initialize + @have_readline = false + end + + # Common routine for reporting debugger error messages. + # Derived classed may want to override this to capture output. + def errmsg(*args) + if Debugger.annotate.to_i > 2 + aprint 'error-begin' + print(*args) + aprint '' + else + print '*** ' + print(*args) + end + end + + # Format msg with gdb-style annotation header + def afmt(msg, newline="\n") + "\032\032#{msg}#{newline}" + end + + def aprint(msg) + print afmt(msg) + end + + end + + class LocalInterface < Interface # :nodoc: + attr_accessor :command_queue + attr_accessor :histfile + attr_accessor :history_save + attr_accessor :history_length + attr_accessor :restart_file + + unless defined?(FILE_HISTORY) + FILE_HISTORY = ".rdebug_hist" + end + def initialize() + super + @command_queue = [] + @have_readline = false + @history_save = true + # take gdb's default + @history_length = ENV["HISTSIZE"] ? ENV["HISTSIZE"].to_i : 256 + @histfile = File.join(ENV["HOME"]||ENV["HOMEPATH"]||".", + FILE_HISTORY) + open(@histfile, 'r') do |file| + file.each do |line| + line.chomp! + Readline::HISTORY << line + end + end if File.exist?(@histfile) + @restart_file = nil + end + + def read_command(prompt) + readline(prompt, true) + end + + def confirm(prompt) + readline(prompt, false) + end + + def print(*args) + STDOUT.printf(*args) + end + + def close + end + + # Things to do before quitting + def finalize + if Debugger.method_defined?("annotate") and Debugger.annotate.to_i > 2 + print "\032\032exited\n\n" + end + if Debugger.respond_to?(:save_history) + Debugger.save_history + end + end + + def readline_support? + @have_readline + end + + private + begin + require 'readline' + class << Debugger + @have_readline = true + define_method(:save_history) do + iface = self.handler.interface + iface.histfile ||= File.join(ENV["HOME"]||ENV["HOMEPATH"]||".", + FILE_HISTORY) + open(iface.histfile, 'w') do |file| + Readline::HISTORY.to_a.last(iface.history_length).each do |line| + file.puts line unless line.strip.empty? + end if defined?(iface.history_save) and iface.history_save + end rescue nil + end + public :save_history + end + Debugger.debug_at_exit do + finalize if respond_to?(:finalize) + end + + def readline(prompt, hist) + Readline::readline(prompt, hist) + end + rescue LoadError + def readline(prompt, hist) + @histfile = '' + @hist_save = false + STDOUT.print prompt + STDOUT.flush + line = STDIN.gets + exit unless line + line.chomp! + line + end + end + end + + class RemoteInterface < Interface # :nodoc: + attr_accessor :command_queue + attr_accessor :histfile + attr_accessor :history_save + attr_accessor :history_length + attr_accessor :restart_file + + def initialize(socket) + @command_queue = [] + @socket = socket + @history_save = false + @history_length = 256 + @histfile = '' + # Do we read the histfile? +# open(@histfile, 'r') do |file| +# file.each do |line| +# line.chomp! +# Readline::HISTORY << line +# end +# end if File.exist?(@histfile) + @restart_file = nil + end + + def close + @socket.close + rescue Exception + end + + def confirm(prompt) + send_command "CONFIRM #{prompt}" + end + + def finalize + end + + def read_command(prompt) + send_command "PROMPT #{prompt}" + end + + def readline_support? + false + end + + def print(*args) + @socket.printf(*args) + end + + private + + def send_command(msg) + @socket.puts msg + result = @socket.gets + raise IOError unless result + result.chomp + end + end + + class ScriptInterface < Interface # :nodoc: + attr_accessor :command_queue + attr_accessor :histfile + attr_accessor :history_save + attr_accessor :history_length + attr_accessor :restart_file + def initialize(file, out, verbose=false) + super() + @command_queue = [] + @file = file.respond_to?(:gets) ? file : open(file) + @out = out + @verbose = verbose + @history_save = false + @history_length = 256 # take gdb default + @histfile = '' + end + + def finalize + end + + def read_command(prompt) + while result = @file.gets + puts "# #{result}" if @verbose + next if result =~ /^\s*#/ + next if result.strip.empty? + break + end + raise IOError unless result + result.chomp! + end + + def readline_support? + false + end + + def confirm(prompt) + 'y' + end + + def print(*args) + @out.printf(*args) + end + + def close + @file.close + end + end +end diff --git a/cli/ruby-debug/.svn/text-base/processor.rb.svn-base b/cli/ruby-debug/.svn/text-base/processor.rb.svn-base new file mode 100644 index 0000000..dbb85a2 --- /dev/null +++ b/cli/ruby-debug/.svn/text-base/processor.rb.svn-base @@ -0,0 +1,474 @@ +require 'ruby-debug/interface' +require 'ruby-debug/command' + +module Debugger + + # Should this be a mixin? + class Processor # :nodoc + attr_accessor :interface + + # Format msg with gdb-style annotation header + def afmt(msg, newline="\n") + "\032\032#{msg}#{newline}" + end + + def aprint(msg) + print afmt(msg) if Debugger.annotate.to_i > 2 + end + + # FIXME: use delegate? + def errmsg(*args) + @interface.errmsg(*args) + end + + # Callers of this routine should make sure to use comma to + # separate format argments rather than %. Otherwise it seems that + # if the string you want to print has format specifier, which + # could happen if you are trying to show say a source-code line + # with "puts" or "print" in it, this print routine will give an + # error saying it is looking for more arguments. + def print(*args) + @interface.print(*args) + end + + end + + class CommandProcessor < Processor # :nodoc: + attr_reader :display + + # FIXME: get from Command regexp method. + @@Show_breakpoints_postcmd = [ + /^\s*b(?:reak)?/, + /^\s* cond(?:ition)? (?:\s+(\d+)\s*(.*))?$/ix, + /^\s*del(?:ete)?(?:\s+(.*))?$/ix, + /^\s* dis(?:able)? (?:\s+(.*))?$/ix, + /^\s* en(?:able)? (?:\s+(.*))?$/ix, + # "tbreak", "clear", + ] + @@Show_annotations_run = [ + /^\s*c(?:ont(?:inue)?)?(?:\s+(.*))?$/, + /^\s*fin(?:ish)?$/, + /^\s*n(?:ext)?([+-])?(?:\s+(.*))?$/, + /^\s*s(?:tep)?([+-])?(?:\s+(.*))?$/ + ] + + @@Show_annotations_postcmd = [ + /^\s* down (?:\s+(.*))? .*$/x, + /^\s* f(?:rame)? (?:\s+ (.*))? \s*$/x, + /^\s* u(?:p)? (?:\s+(.*))?$/x + ] + + def initialize(interface = LocalInterface.new) + @interface = interface + @display = [] + + @mutex = Mutex.new + @last_cmd = nil + @last_file = nil # Filename the last time we stopped + @last_line = nil # line number the last time we stopped + @debugger_breakpoints_were_empty = false # Show breakpoints 1st time + @debugger_displays_were_empty = true # No display 1st time + @debugger_context_was_dead = true # Assume we haven't started. + end + + def interface=(interface) + @mutex.synchronize do + @interface.close if @interface + @interface = interface + end + end + + require 'pathname' # For cleanpath + + # Regularize file name. + # This is also used as a common funnel place if basename is + # desired or if we are working remotely and want to change the + # basename. Or we are eliding filenames. + def self.canonic_file(filename) + # For now we want resolved filenames + if Command.settings[:basename] + File.basename(filename) + else + # Cache this? + Pathname.new(filename).cleanpath.to_s + end + end + + def self.print_location_and_text(file, line) + file_line = "%s:%s\n%s" % [canonic_file(file), line, + Debugger.line_at(file, line)] + # FIXME: use annotations routines + if Debugger.annotate.to_i > 2 + file_line = "\032\032source #{file_line}" + elsif ENV['EMACS'] + file_line = "\032\032#{file_line}" + end + print file_line + end + + def self.protect(mname) + alias_method "__#{mname}", mname + module_eval %{ + def #{mname}(*args) + @mutex.synchronize do + return unless @interface + __#{mname}(*args) + end + rescue IOError, Errno::EPIPE + self.interface = nil + rescue SignalException + raise + rescue Exception + print "INTERNAL ERROR!!! #\{$!\}\n" rescue nil + print $!.backtrace.map{|l| "\t#\{l\}"}.join("\n") rescue nil + end + } + end + + def at_breakpoint(context, breakpoint) + aprint 'stopped' if Debugger.annotate.to_i > 2 + n = Debugger.breakpoints.index(breakpoint) + 1 + file = CommandProcessor.canonic_file(breakpoint.source) + line = breakpoint.pos + if Debugger.annotate.to_i > 2 + print afmt("source #{file}:#{line}") + end + print "Breakpoint %d at %s:%s\n", n, file, line + end + protect :at_breakpoint + + def at_catchpoint(context, excpt) + aprint 'stopped' if Debugger.annotate.to_i > 2 + file = CommandProcessor.canonic_file(context.frame_file(0)) + line = context.frame_line(0) + print afmt("%s:%d" % [file, line]) if ENV['EMACS'] + print "Catchpoint at %s:%d: `%s' (%s)\n", file, line, excpt, excpt.class + fs = context.stack_size + tb = caller(0)[-fs..-1] + if tb + for i in tb + print "\tfrom %s\n", i + end + end + end + protect :at_catchpoint + + def at_tracing(context, file, line) + return if defined?(Debugger::RDEBUG_FILE) && + Debugger::RDEBUG_FILE == file # Don't trace ourself + @last_file = CommandProcessor.canonic_file(file) + file = CommandProcessor.canonic_file(file) + unless file == @last_file and @last_line == line and + Command.settings[:tracing_plus] + print "Tracing(%d):%s:%s %s", + context.thnum, file, line, Debugger.line_at(file, line) + @last_file = file + @last_line = line + end + always_run(context, file, line, 2) + end + protect :at_tracing + + def at_line(context, file, line) + process_commands(context, file, line) + end + protect :at_line + + def at_return(context, file, line) + context.stop_frame = -1 + process_commands(context, file, line) + end + + private + + # The prompt shown before reading a command. + def prompt(context) + p = '(rdb:%s) ' % (context.dead? ? 'post-mortem' : context.thnum) + p = afmt("pre-prompt")+p+"\n"+afmt("prompt") if + Debugger.annotate.to_i > 2 + return p + end + + # Run these commands, for example display commands or possibly + # the list or irb in an "autolist" or "autoirb". + # We return a list of commands that are acceptable to run bound + # to the current state. + def always_run(context, file, line, run_level) + event_cmds = Command.commands.select{|cmd| cmd.event } + + # Remove some commands in post-mortem + event_cmds = event_cmds.find_all do |cmd| + cmd.allow_in_post_mortem + end if context.dead? + + state = State.new do |s| + s.context = context + s.file = file + s.line = line + s.binding = context.frame_binding(0) + s.display = display + s.interface = interface + s.commands = event_cmds + end + @interface.state = state if @interface.respond_to?('state=') + + # Bind commands to the current state. + commands = event_cmds.map{|cmd| cmd.new(state)} + + commands.select do |cmd| + cmd.class.always_run >= run_level + end.each {|cmd| cmd.execute} + return state, commands + end + + # Handle debugger commands + def process_commands(context, file, line) + state, commands = always_run(context, file, line, 1) + $rdebug_state = state if Command.settings[:debuggertesting] + splitter = lambda do |str| + str.split(/;/).inject([]) do |m, v| + if m.empty? + m << v + else + if m.last[-1] == ?\\ + m.last[-1,1] = '' + m.last << ';' << v + else + m << v + end + end + m + end + end + + preloop(commands, context) + CommandProcessor.print_location_and_text(file, line) + while !state.proceed? + input = if @interface.command_queue.empty? + @interface.read_command(prompt(context)) + else + @interface.command_queue.shift + end + break unless input + catch(:debug_error) do + if input == "" + next unless @last_cmd + input = @last_cmd + else + @last_cmd = input + end + splitter[input].each do |cmd| + one_cmd(commands, context, cmd) + postcmd(commands, context, cmd) + end + end + end + postloop(commands, context) + end # process_commands + + def one_cmd(commands, context, input) + if cmd = commands.find{ |c| c.match(input) } + if context.dead? && cmd.class.need_context + p cmd + print "Command is unavailable\n" + else + cmd.execute + end + else + unknown_cmd = commands.find{|cmd| cmd.class.unknown } + if unknown_cmd + unknown_cmd.execute + else + errmsg "Unknown command: \"#{input}\". Try \"help\".\n" + end + end + end + + def preloop(commands, context) + aprint('stopped') if Debugger.annotate.to_i > 2 + if context.dead? + unless @debugger_context_was_dead + if Debugger.annotate.to_i > 2 + aprint('exited') + print "The program finished.\n" + end + @debugger_context_was_dead = true + end + end + + if Debugger.annotate.to_i > 2 + # if we are here, the stack frames have changed outside the + # command loop (e.g. after a "continue" command), so we show + # the annotations again + breakpoint_annotations(commands, context) + display_annotations(commands, context) + annotation('stack', commands, context, "where") + annotation('variables', commands, context, "info variables") unless + context.dead? + end + end + + def postcmd(commands, context, cmd) + if Debugger.annotate.to_i > 0 + cmd = @last_cmd unless cmd + breakpoint_annotations(commands, context) if + @@Show_breakpoints_postcmd.find{|pat| cmd =~ pat} + display_annotations(commands, context) + if @@Show_annotations_postcmd.find{|pat| cmd =~ pat} + annotation('stack', commands, context, "where") if + context.stack_size > 0 + annotation('variables', commands, context, "info variables") unless + context.dead? + end + if not context.dead? and @@Show_annotations_run.find{|pat| cmd =~ pat} + aprint 'starting' if Debugger.annotate.to_i > 2 + + @debugger_context_was_dead = false + end + end + end + + def postloop(commands, context) + end + + def annotation(label, commands, context, cmd) + print afmt(label) + one_cmd(commands, context, cmd) + ### FIXME ANNOTATE: the following line should be deleted + print "\032\032\n" + end + + def breakpoint_annotations(commands, context) + unless Debugger.breakpoints.empty? and @debugger_breakpoints_were_empty + annotation('breakpoints', commands, context, "info breakpoints") + @debugger_breakpoints_were_empty = Debugger.breakpoints.empty? + end + end + + def display_annotations(commands, context) + return if display.empty? +# have_display = display.find{|d| d[0]} +# return unless have_display and @debugger_displays_were_empty +# @debugger_displays_were_empty = have_display + annotation('display', commands, context, "display") + end + + class State # :nodoc: + attr_accessor :context, :file, :line, :binding + attr_accessor :frame_pos, :previous_line, :display + attr_accessor :interface, :commands + + def initialize + super() + @frame_pos = 0 + @previous_line = nil + @proceed = false + yield self + end + + # FIXME: use delegate? + def errmsg(*args) + @interface.errmsg(*args) + end + + def print(*args) + @interface.print(*args) + end + + def confirm(*args) + @interface.confirm(*args) + end + + def proceed? + @proceed + end + + def proceed + @proceed = true + end + end + end + + class ControlCommandProcessor < Processor # :nodoc: + def initialize(interface) + super() + @interface = interface + @debugger_context_was_dead = true # Assume we haven't started. + end + + def process_commands(verbose=false) + control_cmds = Command.commands.select do |cmd| + cmd.allow_in_control + end + state = State.new(@interface, control_cmds) + commands = control_cmds.map{|cmd| cmd.new(state) } + + unless @debugger_context_was_dead + if Debugger.annotate.to_i > 2 + aprint 'exited' + print "The program finished.\n" + end + @debugger_context_was_dead = true + end + + while input = @interface.read_command(prompt(nil)) + print "+#{input}" if verbose + catch(:debug_error) do + if cmd = commands.find{|c| c.match(input) } + cmd.execute + else + errmsg "Unknown command\n" + end + end + end + rescue IOError, Errno::EPIPE + rescue Exception + print "INTERNAL ERROR!!! #{$!}\n" rescue nil + print $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil + ensure + @interface.close + end + + # The prompt shown before reading a command. + # Note: have an unused 'context' parameter to match the local interface. + def prompt(context) + p = '(rdb:ctrl) ' + p = afmt("pre-prompt")+p+"\n"+afmt("prompt") if + Debugger.annotate.to_i > 2 + return p + end + + class State # :nodoc: + attr_reader :commands, :interface + + def initialize(interface, commands) + @interface = interface + @commands = commands + end + + def proceed + end + + def errmsg(*args) + @interface.print(*args) + end + + def print(*args) + @interface.print(*args) + end + + def confirm(*args) + 'y' + end + + def context + nil + end + + def file + errmsg "No filename given.\n" + throw :debug_error + end + end # State + end +end diff --git a/cli/ruby-debug/command.rb b/cli/ruby-debug/command.rb new file mode 100644 index 0000000..f424db9 --- /dev/null +++ b/cli/ruby-debug/command.rb @@ -0,0 +1,228 @@ +require 'rubygems' +require 'columnize' +require 'ruby-debug/helper' + +module Debugger + RUBY_DEBUG_DIR = File.expand_path(File.dirname(__FILE__)) unless + defined?(RUBY_DEBUG_DIR) + + class Command # :nodoc: + SubcmdStruct=Struct.new(:name, :min, :short_help, :long_help) unless + defined?(SubcmdStruct) + + include Columnize + + # Find param in subcmds. param id downcased and can be abbreviated + # to the minimum length listed in the subcommands + def find(subcmds, param) + param.downcase! + for try_subcmd in subcmds do + if (param.size >= try_subcmd.min) and + (try_subcmd.name[0..param.size-1] == param) + return try_subcmd + end + end + return nil + end + + class << self + def commands + @commands ||= [] + end + + DEF_OPTIONS = { + :allow_in_control => false, + :allow_in_post_mortem => true, + :event => true, + :always_run => 0, + :unknown => false, + :need_context => false, + } unless defined?(DEF_OPTIONS) + + def inherited(klass) + DEF_OPTIONS.each do |o, v| + klass.options[o] = v if klass.options[o].nil? + end + commands << klass + end + + def load_commands + Dir[File.join(Debugger.const_get(:RUBY_DEBUG_DIR), 'commands', '*')].each do |file| + require file if file =~ /\.rb$/ + end + Debugger.constants.grep(/Functions$/).map { |name| Debugger.const_get(name) }.each do |mod| + include mod + end + end + + def method_missing(meth, *args, &block) + if meth.to_s =~ /^(.+?)=$/ + @options[$1.intern] = args.first + else + if @options.has_key?(meth) + @options[meth] + else + super + end + end + end + + def options + @options ||= {} + end + + def settings_map + @@settings_map ||= {} + end + private :settings_map + + def settings + unless true and defined? @settings and @settings + @settings = Object.new + map = settings_map + c = class << @settings; self end + if c.respond_to?(:funcall) + c.funcall(:define_method, :[]) do |name| + raise "No such setting #{name}" unless map.has_key?(name) + map[name][:getter].call + end + else + c.send(:define_method, :[]) do |name| + raise "No such setting #{name}" unless map.has_key?(name) + map[name][:getter].call + end + end + c = class << @settings; self end + if c.respond_to?(:funcall) + c.funcall(:define_method, :[]=) do |name, value| + raise "No such setting #{name}" unless map.has_key?(name) + map[name][:setter].call(value) + end + else + c.send(:define_method, :[]=) do |name, value| + raise "No such setting #{name}" unless map.has_key?(name) + map[name][:setter].call(value) + end + end + end + @settings + end + + def register_setting_var(name, default) + var_name = "@@#{name}" + class_variable_set(var_name, default) + register_setting_get(name) { class_variable_get(var_name) } + register_setting_set(name) { |value| class_variable_set(var_name, value) } + end + + def register_setting_get(name, &block) + settings_map[name] ||= {} + settings_map[name][:getter] = block + end + + def register_setting_set(name, &block) + settings_map[name] ||= {} + settings_map[name][:setter] = block + end + end + + register_setting_var(:basename, false) # use basename in showing files? + register_setting_var(:callstyle, :last) + register_setting_var(:debuggertesting, false) + register_setting_var(:force_stepping, false) + register_setting_var(:full_path, true) + register_setting_var(:listsize, 10) # number of lines in list command + register_setting_var(:stack_trace_on_error, false) + register_setting_var(:tracing_plus, false) # different linetrace lines? + + # width of line output. Use COLUMNS value if it exists and is + # not too rediculously large. + width = ENV['COLUMNS'].to_i + width = 80 unless width > 10 + register_setting_var(:width, width) + + if not defined? Debugger::ARGV + Debugger::ARGV = ARGV.clone + end + register_setting_var(:argv, Debugger::ARGV) + + def initialize(state) + @state = state + end + + def match(input) + @match = regexp.match(input) + end + + protected + + # FIXME: use delegate? + def errmsg(*args) + @state.errmsg(*args) + end + + def print(*args) + @state.print(*args) + end + + def confirm(msg) + @state.confirm(msg) == 'y' + end + + def debug_eval(str, b = get_binding) + begin + val = eval(str, b) + rescue StandardError, ScriptError => e + if Command.settings[:stack_trace_on_error] + at = eval("caller(1)", b) + print "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '') + for i in at + print "\tfrom %s\n", i + end + else + print "#{e.class} Exception: #{e.message}\n" + end + throw :debug_error + end + end + + def debug_silent_eval(str) + begin + eval(str, get_binding) + rescue StandardError, ScriptError + nil + end + end + + def get_binding + @state.context.frame_binding(@state.frame_pos) + end + + def line_at(file, line) + Debugger.line_at(file, line) + end + + def get_context(thnum) + Debugger.contexts.find{|c| c.thnum == thnum} + end + end + + Command.load_commands + + # Returns setting object. + # Use Debugger.settings[] and Debugger.settings[]= methods to query and set + # debugger settings. These settings are available: + # + # - :autolist - automatically calls 'list' command on breakpoint + # - :autoeval - evaluates input in the current binding if it's not recognized as a debugger command + # - :autoirb - automatically calls 'irb' command on breakpoint + # - :stack_trace_on_error - shows full stack trace if eval command results with an exception + # - :frame_full_path - displays full paths when showing frame stack + # - :frame_class_names - displays method's class name when showing frame stack + # - :reload_source_on_change - makes 'list' command to always display up-to-date source code + # - :force_stepping - stepping command asways move to the new line + # + def self.settings + Command.settings + end +end diff --git a/cli/ruby-debug/commands/.svn/README.txt b/cli/ruby-debug/commands/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/cli/ruby-debug/commands/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/cli/ruby-debug/commands/.svn/empty-file b/cli/ruby-debug/commands/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/cli/ruby-debug/commands/.svn/entries b/cli/ruby-debug/commands/.svn/entries new file mode 100644 index 0000000..4c0ebeb --- /dev/null +++ b/cli/ruby-debug/commands/.svn/entries @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cli/ruby-debug/commands/.svn/format b/cli/ruby-debug/commands/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/format @@ -0,0 +1 @@ +4 diff --git a/cli/ruby-debug/commands/.svn/prop-base/breakpoints.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/breakpoints.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/breakpoints.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/catchpoint.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/catchpoint.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/catchpoint.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/condition.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/condition.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/condition.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/continue.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/continue.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/continue.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/control.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/control.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/control.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/display.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/display.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/display.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/edit.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/edit.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/edit.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/enable.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/enable.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/enable.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/eval.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/eval.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/eval.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/finish.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/finish.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/finish.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/frame.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/frame.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/frame.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/help.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/help.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/help.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/info.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/info.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/info.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/irb.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/irb.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/irb.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/kill.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/kill.rb.svn-base new file mode 100644 index 0000000..bdbd305 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/kill.rb.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/list.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/list.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/list.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/method.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/method.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/method.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/quit.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/quit.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/quit.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/reload.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/reload.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/reload.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/save.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/save.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/save.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/set.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/set.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/set.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/show.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/show.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/show.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/source.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/source.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/source.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/stepping.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/stepping.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/stepping.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/threads.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/threads.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/threads.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/tmate.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/tmate.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/tmate.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/trace.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/trace.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/trace.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/prop-base/variables.rb.svn-base b/cli/ruby-debug/commands/.svn/prop-base/variables.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/prop-base/variables.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/breakpoints.rb.svn-work b/cli/ruby-debug/commands/.svn/props/breakpoints.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/breakpoints.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/catchpoint.rb.svn-work b/cli/ruby-debug/commands/.svn/props/catchpoint.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/catchpoint.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/condition.rb.svn-work b/cli/ruby-debug/commands/.svn/props/condition.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/condition.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/continue.rb.svn-work b/cli/ruby-debug/commands/.svn/props/continue.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/continue.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/control.rb.svn-work b/cli/ruby-debug/commands/.svn/props/control.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/control.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/display.rb.svn-work b/cli/ruby-debug/commands/.svn/props/display.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/display.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/edit.rb.svn-work b/cli/ruby-debug/commands/.svn/props/edit.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/edit.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/enable.rb.svn-work b/cli/ruby-debug/commands/.svn/props/enable.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/enable.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/eval.rb.svn-work b/cli/ruby-debug/commands/.svn/props/eval.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/eval.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/finish.rb.svn-work b/cli/ruby-debug/commands/.svn/props/finish.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/finish.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/frame.rb.svn-work b/cli/ruby-debug/commands/.svn/props/frame.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/frame.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/help.rb.svn-work b/cli/ruby-debug/commands/.svn/props/help.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/help.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/info.rb.svn-work b/cli/ruby-debug/commands/.svn/props/info.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/info.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/irb.rb.svn-work b/cli/ruby-debug/commands/.svn/props/irb.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/irb.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/kill.rb.svn-work b/cli/ruby-debug/commands/.svn/props/kill.rb.svn-work new file mode 100644 index 0000000..bdbd305 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/kill.rb.svn-work @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/cli/ruby-debug/commands/.svn/props/list.rb.svn-work b/cli/ruby-debug/commands/.svn/props/list.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/list.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/method.rb.svn-work b/cli/ruby-debug/commands/.svn/props/method.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/method.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/quit.rb.svn-work b/cli/ruby-debug/commands/.svn/props/quit.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/quit.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/reload.rb.svn-work b/cli/ruby-debug/commands/.svn/props/reload.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/reload.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/save.rb.svn-work b/cli/ruby-debug/commands/.svn/props/save.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/save.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/set.rb.svn-work b/cli/ruby-debug/commands/.svn/props/set.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/set.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/show.rb.svn-work b/cli/ruby-debug/commands/.svn/props/show.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/show.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/source.rb.svn-work b/cli/ruby-debug/commands/.svn/props/source.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/source.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/stepping.rb.svn-work b/cli/ruby-debug/commands/.svn/props/stepping.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/stepping.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/threads.rb.svn-work b/cli/ruby-debug/commands/.svn/props/threads.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/threads.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/tmate.rb.svn-work b/cli/ruby-debug/commands/.svn/props/tmate.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/tmate.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/trace.rb.svn-work b/cli/ruby-debug/commands/.svn/props/trace.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/trace.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/props/variables.rb.svn-work b/cli/ruby-debug/commands/.svn/props/variables.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/cli/ruby-debug/commands/.svn/props/variables.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/cli/ruby-debug/commands/.svn/text-base/breakpoints.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/breakpoints.rb.svn-base new file mode 100644 index 0000000..d3b9901 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/breakpoints.rb.svn-base @@ -0,0 +1,153 @@ +module Debugger + + # Implements debugger "break" command. + class AddBreakpoint < Command + self.allow_in_control = true + + def regexp + / ^\s* + b(?:reak)? + (?: \s+ #{Position_regexp})? \s* + (?: \s+ (.*))? \s* + $ + /x + end + + def execute + if @match[1] + line, _, _, expr = @match.captures + else + _, file, line, expr = @match.captures + end + if expr + if expr !~ /^\s*if\s+(.+)/ + if file or line + errmsg "Expecting 'if' in breakpoint condition; got: #{expr}.\n" + else + errmsg "Invalid breakpoint location: #{expr}.\n" + end + return + else + expr = $1 + end + end + + brkpt_filename = nil + if file.nil? + unless @state.context + errmsg "We are not in a state that has an associated file.\n" + return + end + brkpt_filename = @state.file + file = File.basename(@state.file) + if line.nil? + # Set breakpoint at current line + line = @state.line.to_s + end + elsif line !~ /^\d+$/ + # See if "line" is a method/function name + klass = debug_silent_eval(file) + if klass && klass.kind_of?(Module) + class_name = klass.name if klass + else + errmsg "Unknown class #{file}.\n" + throw :debug_error + end + else + # FIXME: This should be done in LineCache. + file = File.expand_path(file) if file.index(File::SEPARATOR) || \ + File::ALT_SEPARATOR && file.index(File::ALT_SEPARATOR) + brkpt_filename = file + end + + if line =~ /^\d+$/ + line = line.to_i + if LineCache.cache(brkpt_filename, Command.settings[:reload_source_on_change]) + last_line = LineCache.size(brkpt_filename) + if line > last_line + errmsg("There are only %d lines in file \"%s\".\n", last_line, file) + return + end + unless LineCache.trace_line_numbers(brkpt_filename).member?(line) + errmsg("Line %d is not a stopping point in file \"%s\".\n", line, file) + return + end + else + errmsg("No source file named %s\n" % file) + return unless confirm("Set breakpoint anyway? (y/n) ") + end + + unless @state.context + errmsg "We are not in a state we can add breakpoints.\n" + return + end + b = Debugger.add_breakpoint brkpt_filename, line, expr + print "Breakpoint %d file %s, line %s\n", b.id, brkpt_filename, line.to_s + unless syntax_valid?(expr) + errmsg("Expression \"#{expr}\" syntactically incorrect; breakpoint disabled.\n") + b.enabled = false + end + else + method = line.intern.id2name + b = Debugger.add_breakpoint class_name, method, expr + print "Breakpoint %d at %s::%s\n", b.id, class_name, method.to_s + end + end + + class << self + def help_command + 'break' + end + + def help(cmd) + %{ + b[reak] file:line [if expr] + b[reak] class(.|#)method [if expr] + \tset breakpoint to some position, (optionally) if expr == true + } + end + end + end + + # Implements debugger "delete" command. + class DeleteBreakpointCommand < Command + self.allow_in_control = true + + def regexp + /^\s *del(?:ete)? (?:\s+(.*))?$/ix + end + + def execute + unless @state.context + errmsg "We are not in a state we can delete breakpoints.\n" + return + end + brkpts = @match[1] + unless brkpts + if confirm("Delete all breakpoints? (y or n) ") + Debugger.breakpoints.clear + end + else + brkpts.split(/[ \t]+/).each do |pos| + pos = get_int(pos, "Delete", 1) + return unless pos + unless Debugger.remove_breakpoint(pos) + errmsg "No breakpoint number %d\n", pos + end + end + end + end + + class << self + def help_command + 'delete' + end + + def help(cmd) + %{ + del[ete][ nnn...]\tdelete some or all breakpoints + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/catchpoint.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/catchpoint.rb.svn-base new file mode 100644 index 0000000..964f6ab --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/catchpoint.rb.svn-base @@ -0,0 +1,55 @@ +module Debugger + class CatchCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + /^\s* cat(?:ch)? + (?:\s+ (\S+))? + (?:\s+ (off))? \s* $/ix + end + + def execute + excn = @match[1] + if not excn + # No args given. + info_catch + elsif not @match[2] + # One arg given. + if 'off' == excn + Debugger.catchpoints.clear if + confirm("Delete all catchpoints? (y or n) ") + else + binding = @state.context ? get_binding : TOPLEVEL_BINDING + unless debug_eval("#{excn}.is_a?(Class)", binding) + print "Warning #{excn} is not known to be a Class\n" + end + Debugger.add_catchpoint(excn) + print "Catch exception %s.\n", excn + end + elsif @match[2] != 'off' + errmsg "Off expected. Got %s\n", @match[2] + elsif Debugger.catchpoints.member?(excn) + Debugger.catchpoints.delete(excn) + print "Catch for exception %s removed.\n", excn + else + errmsg "Catch for exception %s not found.\n", excn + end + end + + class << self + def help_command + 'catch' + end + + def help(cmd) + %{ + cat[ch]\t\tsame as "info catch" + cat[ch] [on|off] +\tIntercept when there would otherwise be no handler. +\tWith an "on" or "off", turn handling the exception on or off. + cat[ch] off\tdelete all catchpoints + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/condition.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/condition.rb.svn-base new file mode 100644 index 0000000..322812e --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/condition.rb.svn-base @@ -0,0 +1,49 @@ +module Debugger + + class ConditionCommand < Command # :nodoc: + + def regexp + /^\s* cond(?:ition)? (?:\s+(\d+)\s*(.*))?$/ix + end + + def execute + if not @match[1] + errmsg "\"condition\" must be followed a breakpoint number and expression\n" + else + breakpoints = Debugger.breakpoints.sort_by{|b| b.id } + largest = breakpoints.inject(0) do |largest, b| + largest = b.id if b.id > largest + end + if 0 == largest + print "No breakpoints have been set.\n" + return + end + pos = get_int(@match[1], "Condition", 1, largest) + return unless pos + breakpoints.each do |b| + if b.id == pos + b.expr = @match[2].empty? ? nil : @match[2] + break + end + end + + end + end + + class << self + def help_command + 'condition' + end + + def help(cmd) + %{ + Condition breakpoint-number expression +Specify breakpoint number N to break only if COND is true. +N is an integer and COND is an expression to be evaluated whenever +breakpoint N is reached. If the empty string is used, the condition is removed. + } + end + end + end + +end # module Debugger diff --git a/cli/ruby-debug/commands/.svn/text-base/continue.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/continue.rb.svn-base new file mode 100644 index 0000000..5bee4b3 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/continue.rb.svn-base @@ -0,0 +1,38 @@ +module Debugger + + # Implements debugger "continue" command. + class ContinueCommand < Command + self.allow_in_post_mortem = true + self.need_context = false + def regexp + /^\s* c(?:ont(?:inue)?)? (?:\s+(.*))? $/x + end + + def execute + if @match[1] && !@state.context.dead? + filename = File.expand_path(@state.file) + line_number = get_int(@match[1], "Continue", 0, nil, 0) + return unless line_number + unless LineCache.trace_line_numbers(filename).member?(line_number) + errmsg("Line %d is not a stopping point in file \"%s\".\n", + line_number, filename) + return + end + @state.context.set_breakpoint(filename, line_number) + end + @state.proceed + end + + class << self + def help_command + 'continue' + end + + def help(cmd) + %{ + c[ont[inue]][ nnn]\trun until program ends, hits a breakpoint or reaches line nnn + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/control.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/control.rb.svn-base new file mode 100644 index 0000000..78e11b5 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/control.rb.svn-base @@ -0,0 +1,107 @@ +module Debugger + class RestartCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + / ^\s* + (?:restart|R) + (?:\s+ (\S?.*\S))? \s* + $ + /ix + end + + def execute + if not defined? Debugger::PROG_SCRIPT + errmsg "Don't know name of debugged program\n" + return + end + prog_script = Debugger::PROG_SCRIPT + if not defined? Debugger::RDEBUG_SCRIPT + # FIXME? Should ask for confirmation? + print "Debugger was not called from the outset...\n" + rdebug_script = prog_script + else + rdebug_script = Debugger::RDEBUG_SCRIPT + end + begin + Dir.chdir(Debugger::INITIAL_DIR) + rescue + print "Failed to change initial directory #{Debugger::INITIAL_DIR}" + end + if not File.exist?(File.expand_path(prog_script)) + errmsg "Ruby program #{prog_script} doesn't exist\n" + return + end + if not File.executable?(prog_script) and rdebug_script == prog_script + print "Ruby program #{prog_script} doesn't seem to be executable...\n" + print "We'll add a call to Ruby.\n" + ruby = begin defined?(Gem) ? Gem.ruby : "ruby" rescue "ruby" end + rdebug_script = "#{ruby} -I#{$:.join(' -I')} #{prog_script}" + else + rdebug_script += ' ' + end + if @match[1] + argv = [prog_script] + @match[1].split(/[ \t]+/) + else + if not defined? Command.settings[:argv] + errmsg "Arguments have not been set. Use 'set args' to set them.\n" + return + else + argv = Command.settings[:argv] + end + end + args = argv.join(' ') + + # An execv would be preferable to the "exec" below. + cmd = rdebug_script + args + print "Re exec'ing:\n\t#{cmd}\n" + exec cmd + rescue Errno::EOPNOTSUPP + print "Restart command is not available at this time.\n" + end + + class << self + def help_command + 'restart' + end + + def help(cmd) + %{ + restart|R [args] + Restart the program. This is is a re-exec - all debugger state + is lost. If command arguments are passed those are used. + } + end + end + end + + class InterruptCommand < Command # :nodoc: + self.allow_in_control = true + self.allow_in_post_mortem = false + self.event = false + self.need_context = true + + def regexp + /^\s*i(?:nterrupt)?\s*$/ + end + + def execute + unless Debugger.interrupt_last + context = Debugger.thread_context(Thread.main) + context.interrupt + end + end + + class << self + def help_command + 'interrupt' + end + + def help(cmd) + %{ + i[nterrupt]\tinterrupt the program + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/display.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/display.rb.svn-base new file mode 100644 index 0000000..ff82079 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/display.rb.svn-base @@ -0,0 +1,120 @@ +module Debugger + module DisplayFunctions # :nodoc: + def display_expression(exp) + print "%s = %s\n", exp, debug_silent_eval(exp).to_s + end + + def active_display_expressions? + @state.display.select{|d| d[0]}.size > 0 + end + + def print_display_expressions + n = 1 + for d in @state.display + if d[0] + print "%d: ", n + display_expression(d[1]) + end + n += 1 + end + end + end + + class AddDisplayCommand < Command # :nodoc: + def regexp + /^\s*disp(?:lay)?\s+(.+)$/ + end + + def execute + exp = @match[1] + @state.display.push [true, exp] + print "%d: ", @state.display.size + display_expression(exp) + end + + class << self + def help_command + 'display' + end + + def help(cmd) + %{ + disp[lay] \tadd expression into display expression list + } + end + end + end + + class DisplayCommand < Command # :nodoc: + def self.always_run + Debugger.annotate = 0 unless Debugger.annotate + if Debugger.annotate > 1 + 0 + else + 2 + end + end + + def regexp + /^\s*disp(?:lay)?$/ + end + + def execute + print_display_expressions + end + + class << self + def help_command + 'display' + end + + def help(cmd) + %{ + disp[lay]\t\tdisplay expression list + } + end + end + end + + class DeleteDisplayCommand < Command # :nodoc: + + def regexp + /^\s* undisp(?:lay)? \s* (?:(\S+))?$/x + end + + def execute + unless pos = @match[1] + if confirm("Clear all expressions? (y/n) ") + for d in @state.display + d[0] = false + end + end + else + pos = get_int(pos, "Undisplay") + return unless pos + if @state.display[pos-1] + @state.display[pos-1][0] = nil + else + errmsg "Display expression %d is not defined.\n", pos + end + end + end + + class << self + def help_command + 'undisplay' + end + + def help(cmd) + %{ + undisp[lay][ nnn] + Cancel some expressions to be displayed when program stops. + Arguments are the code numbers of the expressions to stop displaying. + No argument means cancel all automatic-display expressions. + "delete display" has the same effect as this command. + Do "info display" to see current list of code numbers. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/edit.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/edit.rb.svn-base new file mode 100644 index 0000000..ae12887 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/edit.rb.svn-base @@ -0,0 +1,48 @@ +module Debugger + class Edit < Command # :nodoc: + self.allow_in_control = true + def regexp + /^\s* ed(?:it)? (?:\s+(.*))?$/ix + end + + def execute + if not @match[1] or @match[1].strip.empty? + unless @state.context + errmsg "We are not in a state that has an associated file.\n" + return + end + file = @state.file + line_number = @state.line + elsif @pos_match = /([^:]+)[:]([0-9]+)/.match(@match[1]) + file, line_number = @pos_match.captures + else + errmsg "Invalid file/line number specification: #{@match[1]}\n" + return + end + editor = ENV['EDITOR'] || 'ex' + if File.readable?(file) + system("#{editor} +#{line_number} #{file}") + else + errmsg "File \"#{file}\" is not readable.\n" + end + end + + class << self + def help_command + 'edit' + end + + def help(cmd) + %{ + Edit specified file. + +With no argument, edits file containing most recent line listed. +Editing targets can also be specified in this: + FILE:LINENUM, to edit at that line in that file, + } + end + end + end + + +end # module Debugger diff --git a/cli/ruby-debug/commands/.svn/text-base/enable.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/enable.rb.svn-base new file mode 100644 index 0000000..d70f343 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/enable.rb.svn-base @@ -0,0 +1,202 @@ +module Debugger + # Mix-in module to assist in command parsing. + module EnableDisableFunctions # :nodoc: + def enable_disable_breakpoints(is_enable, args) + breakpoints = Debugger.breakpoints.sort_by{|b| b.id } + largest = breakpoints.inject(0) do |largest, b| + largest = b.id if b.id > largest + end + if 0 == largest + errmsg "No breakpoints have been set.\n" + return + end + args.each do |pos| + pos = get_int(pos, "#{is_enable} breakpoints", 1, largest) + return nil unless pos + breakpoints.each do |b| + if b.id == pos + enabled = ("Enable" == is_enable) + if enabled + unless syntax_valid?(b.expr) + errmsg("Expression \"#{b.expr}\" syntactically incorrect; breakpoint remains disabled.\n") + break + end + end + b.enabled = ("Enable" == is_enable) + break + end + end + end + end + + def enable_disable_display(is_enable, args) + if 0 == @state.display.size + errmsg "No display expressions have been set.\n" + return + end + args.each do |pos| + pos = get_int(pos, "#{is_enable} display", 1, @state.display.size) + return nil unless pos + @state.display[pos-1][0] = ("Enable" == is_enable) + end + end + + end + + class EnableCommand < Command # :nodoc: + Subcommands = + [ + ['breakpoints', 2, "Enable specified breakpoints", +"Give breakpoint numbers (separated by spaces) as arguments. +This is used to cancel the effect of the \"disable\" command." + ], + ['display', 2, + "Enable some expressions to be displayed when program stops", +"Arguments are the code numbers of the expressions to resume displaying. +Do \"info display\" to see current list of code numbers."], + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(Subcommands) + + def regexp + /^\s* en(?:able)? (?:\s+(.*))?$/ix + end + + def execute + if not @match[1] + errmsg "\"enable\" must be followed \"display\", \"breakpoints\"" + + " or breakpoint numbers.\n" + else + args = @match[1].split(/[ \t]+/) + param = args.shift + subcmd = find(Subcommands, param) + if subcmd + send("enable_#{subcmd.name}", args) + else + send("enable_breakpoints", args.unshift(param)) + end + end + end + + def enable_breakpoints(args) + enable_disable_breakpoints("Enable", args) + end + + def enable_display(args) + enable_disable_display("Enable", args) + end + + class << self + def help_command + 'enable' + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + str += "\n" + subcmd.long_help if subcmd.long_help + return str + else + return "Invalid 'enable' subcommand '#{args[1]}'." + end + end + s = %{ + Enable some things. + This is used to cancel the effect of the "disable" command. + -- + List of enable subcommands: + -- + } + for subcmd in Subcommands do + s += "enable #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end + + class DisableCommand < Command # :nodoc: + Subcommands = + [ + ['breakpoints', 1, "Disable some breakpoints", +"Arguments are breakpoint numbers with spaces in between. +A disabled breakpoint is not forgotten, but has no effect until reenabled."], + ['display', 1, "Disable some display expressions when program stops", +"Arguments are the code numbers of the expressions to stop displaying. +Do \"info display\" to see current list of code numbers."], + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(Subcommands) + + def regexp + /^\s* dis(?:able)? (?:\s+(.*))?$/ix + end + + def execute + if not @match[1] + errmsg "\"disable\" must be followed \"display\", \"breakpoints\"" + + " or breakpoint numbers.\n" + else + args = @match[1].split(/[ \t]+/) + param = args.shift + subcmd = find(Subcommands, param) + if subcmd + send("disable_#{subcmd.name}", args) + else + send("disable_breakpoints", args.unshift(param)) + end + end + end + + def disable_breakpoints(args) + enable_disable_breakpoints("Disable", args) + end + + def disable_display(args) + enable_disable_display("Disable", args) + end + + class << self + def help_command + 'disable' + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + str += "\n" + subcmd.long_help if subcmd.long_help + return str + else + return "Invalid 'disable' subcommand '#{args[1]}'." + end + end + s = %{ + Disable some things. + + A disabled item is not forgotten, but has no effect until reenabled. + Use the "enable" command to have it take effect again. + -- + List of disable subcommands: + -- + } + for subcmd in Subcommands do + s += "disable #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end + +end # module Debugger diff --git a/cli/ruby-debug/commands/.svn/text-base/eval.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/eval.rb.svn-base new file mode 100644 index 0000000..f752047 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/eval.rb.svn-base @@ -0,0 +1,176 @@ +module Debugger + module EvalFunctions # :nodoc: + def run_with_binding + binding = @state.context ? get_binding : TOPLEVEL_BINDING + $__dbg_interface = @state.interface + eval(<<-EOC, binding) + __dbg_verbose_save=$VERBOSE; $VERBOSE=false + def dbg_print(*args) + $__dbg_interface.print(*args) + end + remove_method :puts if self.respond_to?(:puts) && + defined?(remove_method) + def dbg_puts(*args) + $__dbg_interface.print(*args) + $__dbg_interface.print("\n") + end + $VERBOSE=__dbg_verbose_save + EOC + yield binding + ensure + $__dbg_interface = nil + end + end + + class EvalCommand < Command # :nodoc: + self.allow_in_control = true + + register_setting_get(:autoeval) do + EvalCommand.unknown + end + register_setting_set(:autoeval) do |value| + EvalCommand.unknown = value + end + + def match(input) + @input = input + super + end + + def regexp + /^\s*(p|e(?:val)?)\s+/ + end + + def execute + expr = @match ? @match.post_match : @input + run_with_binding do |b| + print "%s\n", debug_eval(expr, b).inspect + end + end + + class << self + def help_command + %w|p eval| + end + + def help(cmd) + if cmd == 'p' + %{ + p expression\tevaluate expression and print its value + } + else + %{ + e[val] expression\tevaluate expression and print its value, + \t\t\talias for p. + * NOTE - to turn on autoeval, use 'set autoeval' + } + end + end + end + end + + class PPCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + /^\s*pp\s+/ + end + + def execute + out = StringIO.new + run_with_binding do |b| + PP.pp(debug_eval(@match.post_match, b), out) + end + print out.string + rescue + out.puts $!.message + end + + class << self + def help_command + 'pp' + end + + def help(cmd) + %{ + pp expression\tevaluate expression and pretty-print its value + } + end + end + end + + class PutLCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + /^\s*putl\s+/ + end + + def execute + out = StringIO.new + run_with_binding do |b| + vals = debug_eval(@match.post_match, b) + if vals.is_a?(Array) + vals = vals.map{|item| item.to_s} + print "%s\n", columnize(vals, self.class.settings[:width]) + else + PP.pp(vals, out) + print out.string + end + end + rescue + out.puts $!.message + end + + class << self + def help_command + 'putl' + end + + def help(cmd) + %{ + putl expression\t\tevaluate expression, an array, and columnize its value + } + end + end + end + + class PSCommand < Command # :nodoc: + self.allow_in_control = true + + include EvalFunctions + + def regexp + /^\s*ps\s+/ + end + + def execute + out = StringIO.new + run_with_binding do |b| + vals = debug_eval(@match.post_match, b) + if vals.is_a?(Array) + vals = vals.map{|item| item.to_s} + print "%s\n", columnize(vals.sort!, self.class.settings[:width]) + else + PP.pp(vals, out) + print out.string + end + end + rescue + out.puts $!.message + end + + class << self + def help_command + 'ps' + end + + def help(cmd) + %{ + ps expression\tevaluate expression, an array, sort, and columnize its value + } + end + end + end + +end diff --git a/cli/ruby-debug/commands/.svn/text-base/finish.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/finish.rb.svn-base new file mode 100644 index 0000000..c7b77ff --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/finish.rb.svn-base @@ -0,0 +1,42 @@ +module Debugger + # Implements the debugger 'finish' command. + class FinishCommand < Command + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s*fin(?:ish)? (?:\s+(.*))?$/x + end + + def execute + max_frame = @state.context.stack_size - @state.frame_pos + if !@match[1] or @match[1].empty? + frame_pos = @state.frame_pos + else + frame_pos = get_int(@match[1], "Finish", 0, max_frame-1, 0) + return nil unless frame_pos + end + @state.context.stop_frame = frame_pos + @state.frame_pos = 0 + @state.proceed + end + + class << self + def help_command + 'finish' + end + + def help(cmd) + %{ + fin[ish] [frame-number]\tExecute until selected stack frame returns. + +If no frame number is given, we run until the currently selected frame +returns. The currently selected frame starts out the most-recent +frame or 0 if no frame positioning (e.g "up", "down" or "frame") has +been performed. If a frame number is given we run until that frame +returns. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/frame.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/frame.rb.svn-base new file mode 100644 index 0000000..f9b6f26 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/frame.rb.svn-base @@ -0,0 +1,301 @@ +module Debugger + # Mix-in module to assist in command parsing. + module FrameFunctions # :nodoc: + def adjust_frame(frame_pos, absolute, context=@state.context) + @state.frame_pos = 0 if context != @state.context + if absolute + if frame_pos < 0 + abs_frame_pos = context.stack_size + frame_pos + else + abs_frame_pos = frame_pos + end + else + abs_frame_pos = @state.frame_pos + frame_pos + end + + if abs_frame_pos >= context.stack_size then + errmsg "Adjusting would put us beyond the oldest (initial) frame.\n" + return + elsif abs_frame_pos < 0 then + errmsg "Adjusting would put us beyond the newest (innermost) frame.\n" + return + end + if @state.frame_pos != abs_frame_pos then + @state.previous_line = nil + @state.frame_pos = abs_frame_pos + end + + @state.file = context.frame_file(@state.frame_pos) + @state.line = context.frame_line(@state.frame_pos) + + print_frame(@state.frame_pos, true) + end + + def get_frame_call(prefix, pos, context) + id = context.frame_method(pos) + klass = context.frame_class(pos) + call_str = "" + if id + args = context.frame_args(pos) + locals = context.frame_locals(pos) + if Command.settings[:callstyle] != :short && klass + if Command.settings[:callstyle] == :tracked + arg_info = context.frame_args_info(pos) + end + call_str << "#{klass}." + end + call_str << id.id2name + if args.any? + call_str << "(" + args.each_with_index do |name, i| + case Command.settings[:callstyle] + when :short + call_str += "%s, " % [name] + when :last + klass = locals[name].class + if klass.inspect.size > 20+3 + klass = klass.inspect[0..20]+"..." + end + call_str += "%s#%s, " % [name, klass] + when :tracked + if arg_info && arg_info.size > i + call_str += "#{name}: #{arg_info[i].inspect}, " + else + call_str += "%s, " % name + end + end + if call_str.size > self.class.settings[:width] - prefix.size + # Strip off trailing ', ' if any but add stuff for later trunc + call_str[-2..-1] = ",...XX" + break + end + end + call_str[-2..-1] = ")" # Strip off trailing ', ' if any + end + end + return call_str + end + + def print_frame(pos, adjust = false, context=@state.context) + file = context.frame_file(pos) + line = context.frame_line(pos) + klass = context.frame_class(pos) + + unless Command.settings[:full_path] + path_components = file.split(/[\\\/]/) + if path_components.size > 3 + path_components[0...-3] = '...' + file = path_components.join(File::ALT_SEPARATOR || File::SEPARATOR) + end + end + + frame_num = "#%d " % pos + call_str = get_frame_call(frame_num, pos, context) + file_line = "at line %s:%d\n" % [CommandProcessor.canonic_file(file), line] + print frame_num + unless call_str.empty? + print call_str + print ' ' + if call_str.size + frame_num.size + file_line.size > self.class.settings[:width] + print "\n " + end + end + print file_line + if ENV['EMACS'] && adjust + fmt = (Debugger.annotate.to_i > 1 ? + "\032\032source %s:%d\n" : "\032\032%s:%d\n") + print fmt % [CommandProcessor.canonic_file(file), line] + end + end + + # Check if call stack is truncated. This can happen if + # Debugger.start is not called low enough in the call stack. An + # array of additional callstack lines from caller is returned if + # definitely truncated, false if not, and nil if we don't know. + # + # We determine truncation based on a passed in sentinal set via + # caller which can be nil. + # + # First we see if we can find our position in caller. If so, then + # we compare context position to that in caller using sentinal + # as a place to start ignoring additional caller entries. sentinal + # is set by rdebug, but if it's not set, i.e. nil then additional + # entries are presumably ones that we haven't recorded in context + def truncated_callstack?(context, sentinal=nil, cs=caller) + recorded_size = context.stack_size + to_find_fl = "#{context.frame_file(0)}:#{context.frame_line(0)}" + top_discard = false + cs.each_with_index do |fl, i| + fl.gsub!(/in `.*'$/, '') + fl.gsub!(/:$/, '') + if fl == to_find_fl + top_discard = i + break + end + end + if top_discard + cs = cs[top_discard..-1] + return false unless cs + return cs unless sentinal + if cs.size > recorded_size+2 && cs[recorded_size+2] != sentinal + # caller seems to truncate recursive calls and we don't. + # See if we can find sentinal in the first 0..recorded_size+1 entries + return false if cs[0..recorded_size+1].any?{ |f| f==sentinal } + return cs + end + return false + end + return nil + end + + + end + + # Implements debugger "where" or "backtrace" command. + class WhereCommand < Command + def regexp + /^\s*(?:w(?:here)?|bt|backtrace)$/ + end + + def execute + (0...@state.context.stack_size).each do |idx| + if idx == @state.frame_pos + print "--> " + else + print " " + end + print_frame(idx) + + end + if truncated_callstack?(@state.context, Debugger.start_sentinal) + print "Warning: saved frames may be incomplete; compare with caller(0).\n" + end + end + + class << self + def help_command + %w|where backtrace| + end + + def help(cmd) + s = if cmd == 'where' + %{ + w[here]\tdisplay stack frames + } + else + %{ + bt|backtrace\t\talias for where - display stack frames + } + end + s += %{ +Print the entire stack frame. Each frame is numbered, the most recent +frame is 0. frame number can be referred to in the "frame" command; +"up" and "down" add or subtract respectively to frame numbers shown. +The position of the current frame is marked with -->. } + end + end + end + + class UpCommand < Command # :nodoc: + def regexp + /^\s* u(?:p)? (?:\s+(.*))?$/x + end + + def execute + pos = get_int(@match[1], "Up") + return unless pos + adjust_frame(pos, false) + end + + class << self + def help_command + 'up' + end + + def help(cmd) + %{ + up[count]\tmove to higher frame + } + end + end + end + + class DownCommand < Command # :nodoc: + def regexp + /^\s* down (?:\s+(.*))? .*$/x + end + + def execute + pos = get_int(@match[1], "Down") + return unless pos + adjust_frame(-pos, false) + end + + class << self + def help_command + 'down' + end + + def help(cmd) + %{ + down[count]\tmove to lower frame + } + end + end + end + + class FrameCommand < Command # :nodoc: + def regexp + / ^\s* + f(?:rame)? + (?: \s+ (\S+))? \s* + (?: thread \s+ (.*))? \s* + $/x + end + + def execute + if not @match[1] + pos = 0 + else + pos = get_int(@match[1], "Frame") + return unless pos + end + if @match[2] + context = parse_thread_num('frame', @match[2]) + unless context + errmsg "Thread #{@match[2]} doesn't exist.\n" + return + end + else + context = @state.context + end + adjust_frame(pos, true, context) + end + + class << self + def help_command + 'frame' + end + + def help(cmd) + %{ + f[rame] [frame-number [thread thread-number]] + Move the current frame to the specified frame number, or the + 0 if no frame-number has been given. + + A negative number indicates position from the other end. So + 'frame -1' moves to the oldest frame, and 'frame 0' moves to + the newest frame. + + Without an argument, the command prints the current stack + frame. Since the current position is redisplayed, it may trigger a + resyncronization if there is a front end also watching over + things. + + If a thread number is given then we set the context for evaluating + expressions to that frame of that thread. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/help.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/help.rb.svn-base new file mode 100644 index 0000000..1144621 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/help.rb.svn-base @@ -0,0 +1,56 @@ +module Debugger + + # Implements debugger "help" command. + class HelpCommand < Command + self.allow_in_control = true + + def regexp + /^\s* h(?:elp)? (?:\s+(.+))? $/x + end + + def execute + if @match[1] + args = @match[1].split + cmds = @state.commands.select do |cmd| + [cmd.help_command].flatten.include?(args[0]) + end + else + args = @match[1] + cmds = [] + end + unless cmds.empty? + help = cmds.map{ |cmd| cmd.help(args) }.join + help = help.split("\n").map{|l| l.gsub(/^ +/, '')} + help.shift if help.first && help.first.empty? + help.pop if help.last && help.last.empty? + print help.join("\n") + else + if args and args[0] + errmsg "Undefined command: \"#{args[0]}\". Try \"help\"." + else + print "ruby-debug help v#{Debugger::VERSION}\n" unless + self.class.settings[:debuggertesting] + print "Type 'help ' for help on a specific command\n\n" + print "Available commands:\n" + cmds = @state.commands.map{ |cmd| cmd.help_command } + cmds = cmds.flatten.uniq.sort + print columnize(cmds, self.class.settings[:width]) + end + end + print "\n" + end + + class << self + def help_command + 'help' + end + + def help(cmd) + %{ + h[elp]\t\tprint this help + h[elp] command\tprint help on command + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/info.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/info.rb.svn-base new file mode 100644 index 0000000..3fac50c --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/info.rb.svn-base @@ -0,0 +1,469 @@ +module Debugger + module InfoFunctions # :nodoc: + def info_catch(*args) + unless @state.context + print "No frame selected.\n" + return + end + if Debugger.catchpoints and not Debugger.catchpoints.empty? + # FIXME: show whether Exception is valid or not + # print "Exception: is_a?(Class)\n" + Debugger.catchpoints.each do |exception, hits| + # print "#{exception}: #{exception.is_a?(Class)}\n" + print "#{exception}\n" + end + else + print "No exceptions set to be caught.\n" + end + end + end + + # Implements debugger "info" command. + class InfoCommand < Command + self.allow_in_control = true + Subcommands = + [ + ['args', 1, 'Argument variables of current stack frame'], + ['breakpoints', 1, 'Status of user-settable breakpoints', + 'Without argument, list info about all breakpoints. With an +integer argument, list info on that breakpoint.'], + ['catch', 3, 'Exceptions that can be caught in the current stack frame'], + ['display', 2, 'Expressions to display when program stops'], + ['file', 4, 'Info about a particular file read in', +' +After the file name is supplied, you can list file attributes that +you wish to see. + +Attributes include: "all", "basic", "breakpoint", "lines", "mtime", "path" +and "sha1".'], + ['files', 5, 'File names and timestamps of files read in'], + ['global_variables', 2, 'Global variables'], + ['instance_variables', 2, + 'Instance variables of the current stack frame'], + ['line', 2, + 'Line number and file name of current position in source file'], + ['locals', 2, 'Local variables of the current stack frame'], + ['program', 2, 'Execution status of the program'], + ['stack', 2, 'Backtrace of the stack'], + ['thread', 6, 'List info about thread NUM', ' +If no thread number is given, we list info for all threads. \'terse\' and \'verbose\' +options are possible. If terse, just give summary thread name information. See +"help info threads" for more detail about this summary information. + +If \'verbose\' appended to the end of the command, then the entire +stack trace is given for each thread.'], + ['threads', 7, 'information of currently-known threads', ' +This information includes whether the thread is current (+), if it is +suspended ($), or ignored (!). The thread number and the top stack +item. If \'verbose\' is given then the entire stack frame is shown.'], + ['variables', 1, + 'Local and instance variables of the current stack frame'] + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(Subcommands) + + InfoFileSubcommands = + [ + ['all', 1, + 'All file information available - breakpoints, lines, mtime, path, and sha1'], + ['basic', 2, + 'basic information - path, number of lines'], + ['breakpoints', 2, 'Show trace line numbers', + 'These are the line number where a breakpoint can be set.'], + ['lines', 1, 'Show number of lines in the file'], + ['mtime', 1, 'Show modification time of file'], + ['path', 4, 'Show full file path name for file'], + ['sha1', 1, 'Show SHA1 hash of contents of the file'] + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(InfoFileSubcommands) + + InfoThreadSubcommands = + [ + ['terse', 1, 'summary information'], + ['verbose', 1, 'summary information and stack frame info'], + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(InfoThreadSubcommands) + + def regexp + /^\s* i(?:nfo)? (?:\s+(.*))?$/ix + end + + def execute + if @match[1].empty? + errmsg "\"info\" must be followed by the name of an info command:\n" + print "List of info subcommands:\n\n" + for subcmd in Subcommands do + print "info #{subcmd.name} -- #{subcmd.short_help}\n" + end + else + args = @match[1].split(/[ \t]+/) + param = args.shift + subcmd = find(Subcommands, param) + if subcmd + send("info_#{subcmd.name}", *args) + else + errmsg "Unknown info command #{param}\n" + end + end + end + + def info_args(*args) + unless @state.context + print "No frame selected.\n" + return + end + locals = @state.context.frame_locals(@state.frame_pos) + args = @state.context.frame_args(@state.frame_pos) + args.each do |name| + s = "#{name} = #{locals[name].inspect}" + if s.size > self.class.settings[:width] + s[self.class.settings[:width]-3 .. -1] = "..." + end + print "#{s}\n" + end + end + + def info_breakpoints(*args) + unless @state.context + print "info breakpoints not available here.\n" + return + end + unless Debugger.breakpoints.empty? + brkpts = Debugger.breakpoints.sort_by{|b| b.id} + unless args.empty? + a = args.map{|a| a.to_i} + brkpts = brkpts.select{|b| a.member?(b.id)} + if brkpts.empty? + errmsg "No breakpoints found among list given.\n" + return + end + end + print "Num Enb What\n" + brkpts.each do |b| + if b.expr.nil? + print "%3d %s at %s:%s\n", + b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos + else + print "%3d %s at %s:%s if %s\n", + b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos, b.expr + end + hits = b.hit_count + if hits > 0 + s = (hits > 1) ? 's' : '' + print "\tbreakpoint already hit #{hits} time#{s}\n" + end + end + else + print "No breakpoints.\n" + end + end + + def info_display(*args) + unless @state.context + print "info display not available here.\n" + return + end + if @state.display.find{|d| d[0]} + print "Auto-display expressions now in effect:\n" + print "Num Enb Expression\n" + n = 1 + for d in @state.display + print "%3d: %s %s\n", n, (d[0] ? 'y' : 'n'), d[1] if + d[0] != nil + n += 1 + end + else + print "There are no auto-display expressions now.\n" + end + end + + def info_file(*args) + unless args[0] + info_files + return + end + file = args[0] + param = args[1] + + param = 'basic' unless param + subcmd = find(InfoFileSubcommands, param) + unless subcmd + errmsg "Invalid parameter #{param}\n" + return + end + + unless LineCache::cached?(file) + unless LineCache::cached_script?(file) + print "File #{file} is not cached\n" + return + end + LineCache::cache(file, Command.settings[:reload_source_on_change]) + end + + print "File %s", file + path = LineCache.path(file) + if %w(all basic path).member?(subcmd.name) and path != file + print " - %s\n", path + else + print "\n" + end + + if %w(all basic lines).member?(subcmd.name) + lines = LineCache.size(file) + print "\t %d lines\n", lines if lines + end + + if %w(all breakpoints).member?(subcmd.name) + breakpoints = LineCache.trace_line_numbers(file) + if breakpoints + print "\tbreakpoint line numbers:\n" + print columnize(breakpoints.to_a.sort, self.class.settings[:width]) + end + end + + if %w(all mtime).member?(subcmd.name) + stat = LineCache.stat(file) + print "\t%s\n", stat.mtime if stat + end + if %w(all sha1).member?(subcmd.name) + print "\t%s\n", LineCache.sha1(file) + end + end + + def info_files(*args) + files = LineCache::cached_files + files += SCRIPT_LINES__.keys unless 'stat' == args[0] + files.uniq.sort.each do |file| + stat = LineCache::stat(file) + path = LineCache::path(file) + print "File %s", file + if path and path != file + print " - %s\n", path + else + print "\n" + end + print "\t%s\n", stat.mtime if stat + end + end + + def info_instance_variables(*args) + unless @state.context + print "info instance_variables not available here.\n" + return + end + obj = debug_eval('self') + var_list(obj.instance_variables) + end + + def info_line(*args) + unless @state.context + errmsg "info line not available here.\n" + return + end + print "Line %d of \"%s\"\n", @state.line, @state.file + end + + def info_locals(*args) + unless @state.context + errmsg "info line not available here.\n" + return + end + locals = @state.context.frame_locals(@state.frame_pos) + locals.keys.sort.each do |name| + ### FIXME: make a common routine + begin + s = "#{name} = #{locals[name].inspect}" + rescue + begin + s = "#{name} = #{locals[name].to_s}" + rescue + s = "*Error in evaluation*" + end + end + if s.size > self.class.settings[:width] + s[self.class.settings[:width]-3 .. -1] = "..." + end + print "#{s}\n" + end + end + + def info_program(*args) + if not @state.context + print "The program being debugged is not being run.\n" + return + elsif @state.context.dead? + print "The program crashed.\n" + if Debugger.last_exception + print("Exception: #{Debugger.last_exception.inspect}\n") + end + return + end + + print "Program stopped. " + case @state.context.stop_reason + when :step + print "It stopped after stepping, next'ing or initial start.\n" + when :breakpoint + print("It stopped at a breakpoint.\n") + when :catchpoint + print("It stopped at a catchpoint.\n") + when :catchpoint + print("It stopped at a catchpoint.\n") + else + print "unknown reason: %s\n" % @state.context.stop_reason.to_s + end + end + + def info_stack(*args) + if not @state.context + errmsg "info stack not available here.\n" + return + end + (0...@state.context.stack_size).each do |idx| + if idx == @state.frame_pos + print "--> " + else + print " " + end + print_frame(idx) + end + end + + def info_thread_preamble(arg) + if not @state.context + errmsg "info threads not available here.\n" + return false, false + end + verbose = if arg + subcmd = find(InfoThreadSubcommands, arg) + unless subcmd + errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n" + return false, false + end + 'verbose' == subcmd.name + else + false + end + return true, verbose + end + private :info_thread_preamble + + def info_threads(*args) + ok, verbose = info_thread_preamble(args[0]) + return unless ok + threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c| + display_context(c, !verbose) + if verbose and not c.ignored? + (0...c.stack_size).each do |idx| + print "\t" + print_frame(idx, false, c) + end + end + end + end + + def info_thread(*args) + unless args[0] + info_threads(args[0]) + return + end + ok, verbose = info_thread_preamble(args[1]) + return unless ok + c = parse_thread_num("info thread" , args[0]) + return unless c + display_context(c, !verbose) + if verbose and not c.ignored? + (0...c.stack_size).each do |idx| + print "\t" + print_frame(idx, false, c) + end + end + end + + def info_global_variables(*args) + unless @state.context + errmsg "info global_variables not available here.\n" + return + end + var_list(global_variables) + end + + def info_variables(*args) + if not @state.context + errmsg "info variables not available here.\n" + return + end + obj = debug_eval('self') + locals = @state.context.frame_locals(@state.frame_pos) + locals['self'] = @state.context.frame_self(@state.frame_pos) + locals.keys.sort.each do |name| + next if name =~ /^__dbg_/ # skip debugger pollution + ### FIXME: make a common routine + begin + s = "#{name} = #{locals[name].inspect}" + rescue + begin + s = "#{name} = #{locals[name].to_s}" + rescue + s = "#{name} = *Error in evaluation*" + end + end + if s.size > self.class.settings[:width] + s[self.class.settings[:width]-3 .. -1] = "..." + end + s.gsub!('%', '%%') # protect against printf format strings + print "#{s}\n" + end + var_list(obj.instance_variables, obj.instance_eval{binding()}) + var_class_self + end + + class << self + def help_command + 'info' + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + if 'file' == subcmd.name and args[2] + s = args[2] + subsubcmd = InfoFileSubcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subsubcmd + str += "\n" + subsubcmd.short_help + '.' + else + str += "\nInvalid file attribute #{args[2]}." + end + else + str += "\n" + subcmd.long_help if subcmd.long_help + end + return str + else + return "Invalid 'info' subcommand '#{args[1]}'." + end + end + s = %{ + Generic command for showing things about the program being debugged. + -- + List of info subcommands: + -- + } + for subcmd in Subcommands do + s += "info #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/irb.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/irb.rb.svn-base new file mode 100644 index 0000000..2493e80 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/irb.rb.svn-base @@ -0,0 +1,123 @@ +require 'irb' + +module IRB # :nodoc: + module ExtendCommand # :nodoc: + class Continue # :nodoc: + def self.execute(conf) + throw :IRB_EXIT, :cont + end + end + class Next # :nodoc: + def self.execute(conf) + throw :IRB_EXIT, :next + end + end + class Step # :nodoc: + def self.execute(conf) + throw :IRB_EXIT, :step + end + end + end + ExtendCommandBundle.def_extend_command "cont", :Continue + ExtendCommandBundle.def_extend_command "n", :Next + ExtendCommandBundle.def_extend_command "step", :Step + + def self.start_session(binding) + unless @__initialized + args = ARGV.dup + ARGV.replace([]) + IRB.setup(nil) + ARGV.replace(args) + @__initialized = true + end + + workspace = WorkSpace.new(binding) + + irb = Irb.new(workspace) + + @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] + @CONF[:MAIN_CONTEXT] = irb.context + + catch(:IRB_EXIT) do + irb.eval_input + end + end +end + +module Debugger + + # Implements debugger "irb" command. + class IRBCommand < Command + + register_setting_get(:autoirb) do + IRBCommand.always_run + end + register_setting_set(:autoirb) do |value| + IRBCommand.always_run = value + end + + def regexp + /^\s* irb + (?:\s+(-d))? + \s*$/x + end + + def execute + unless @state.interface.kind_of?(LocalInterface) + print "Command is available only in local mode.\n" + throw :debug_error + end + + save_trap = trap("SIGINT") do + throw :IRB_EXIT, :cont if $rdebug_in_irb + end + + add_debugging = @match.is_a?(Array) && '-d' == @match[1] + $rdebug_state = @state if add_debugging + $rdebug_in_irb = true + cont = IRB.start_session(get_binding) + case cont + when :cont + @state.proceed + when :step + force = Command.settings[:force_stepping] + @state.context.step(1, force) + @state.proceed + when :next + force = Command.settings[:force_stepping] + @state.context.step_over(1, @state.frame_pos, force) + @state.proceed + else + file = @state.context.frame_file(0) + line = @state.context.frame_line(0) + CommandProcessor.print_location_and_text(file, line) + @state.previous_line = nil + end + + ensure + $rdebug_in_irb = nil + $rdebug_state = nil if add_debugging + trap("SIGINT", save_trap) if save_trap + end + + class << self + def help_command + 'irb' + end + + def help(cmd) + %{ + irb [-d]\tstarts an Interactive Ruby (IRB) session. + +If -d is added you can get access to debugger state via the global variable +$RDEBUG_state. + +irb is extended with methods "cont", "n" and "step" which +run the corresponding debugger commands. In contrast to the real debugger +commands these commands don't allow command arguments. + } + end + end + end +end + diff --git a/cli/ruby-debug/commands/.svn/text-base/kill.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/kill.rb.svn-base new file mode 100644 index 0000000..da5d05e --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/kill.rb.svn-base @@ -0,0 +1,51 @@ +module Debugger + + # Implements debugger "kill" command + class KillCommand < Command + self.allow_in_control = true + + def regexp + / ^\s* + (?:kill) \s* + (?:\s+(\S+))?\s* + $ + /ix + end + + def execute + puts @match[1] + if @match[1] + signame = @match[1] + unless Signal.list.member?(signame) + errmsg("signal name #{signame} is not a signal I know about\n") + return false + end + if 'KILL' == signame: + @state.interface.finalize + end + else + if not confirm("Really kill? (y/n) ") + return + else + signame = 'KILL' + end + end + Process.kill(signame, Process.pid) + end + + class << self + def help_command + %w[kill] + end + + def help(cmd) + %{ + kill [SIGNAL] + + Send [signal] to Process.pid +Equivalent of Process.kill(Process.pid) + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/list.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/list.rb.svn-base new file mode 100644 index 0000000..165732f --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/list.rb.svn-base @@ -0,0 +1,94 @@ +module Debugger + # Implements debugger "list" command. + class ListCommand < Command + + register_setting_get(:autolist) do + ListCommand.always_run + end + register_setting_set(:autolist) do |value| + ListCommand.always_run = value + end + + def regexp + /^\s* l(?:ist)? (?:\s*([-=])|\s+(.+))? $/x + end + + def execute + listsize = Command.settings[:listsize] + if !@match || !(@match[1] || @match[2]) + b = @state.previous_line ? + @state.previous_line + listsize : @state.line - (listsize/2) + e = b + listsize - 1 + elsif @match[1] == '-' + b = if @state.previous_line + if @state.previous_line > 0 + @state.previous_line - listsize + else + @state.previous_line + end + else + @state.line - (listsize/2) + end + e = b + listsize - 1 + elsif @match[1] == '=' + @state.previous_line = nil + b = @state.line - (listsize/2) + e = b + listsize -1 + else + b, e = @match[2].split(/[-,]/) + if e + b = b.to_i + e = e.to_i + else + b = b.to_i - (listsize/2) + e = b + listsize - 1 + end + end + @state.previous_line = display_list(b, e, @state.file, @state.line) + end + + class << self + def help_command + 'list' + end + + def help(cmd) + %{ + l[ist]\t\tlist forward + l[ist] -\tlist backward + l[ist] =\tlist current line + l[ist] nn-mm\tlist given lines + * NOTE - to turn on autolist, use 'set autolist' + } + end + end + + private + + # Show FILE from line B to E where CURRENT is the current line number. + # If we can show from B to E then we return B, otherwise we return the + # previous line @state.previous_line. + def display_list(b, e, file, current) + print "[%d, %d] in %s\n", b, e, file + lines = LineCache::getlines(file, + Command.settings[:reload_source_on_change]) + if lines + return @state.previous_line if b >= lines.size + e = lines.size if lines.size < e + [b, 1].max.upto(e) do |n| + if n > 0 && lines[n-1] + if n == current + print "=> %d %s\n", n, lines[n-1].chomp + else + print " %d %s\n", n, lines[n-1].chomp + end + end + end + else + errmsg "No sourcefile available for %s\n", file + return @state.previous_line + end + return e == lines.size ? @state.previous_line : b + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/method.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/method.rb.svn-base new file mode 100644 index 0000000..1d31ead --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/method.rb.svn-base @@ -0,0 +1,84 @@ +module Debugger + + begin + require 'methodsig' + have_methodsig = true + rescue LoadError + have_methodsig = false + end + + # Implements the debugger 'method sig' command. + class MethodSigCommand < Command + def regexp + /^\s*m(?:ethod)?\s+sig(?:nature)?\s+(\S+)\s*$/ + end + + def execute + obj = debug_eval('method(:%s)' % @match[1]) + if obj.is_a?(Method) + begin + print "%s\n", obj.signature.to_s + rescue + errmsg("Can't get signature for '#{@match[1]}'\n") + end + else + errmsg("Can't make method out of '#{@match[1]}'\n") + end + end + + class << self + def help_command + 'method' + end + + def help(cmd) + %{ + m[ethod] sig[nature] \tshow the signature of a method + } + end + end + end if have_methodsig + + # Implements the debugger 'method' command. + class MethodCommand < Command + def regexp + /^\s*m(?:ethod)?\s+((iv)|(i(:?nstance\s+)?)\s+)?/ + end + + def execute + if @match[1] == "iv" + obj = debug_eval(@match.post_match) + obj.instance_variables.sort.each do |v| + print "%s = %s\n", v, obj.instance_variable_get(v).inspect + end + elsif @match[1] + obj = debug_eval(@match.post_match) + print "%s\n", columnize(obj.methods.sort(), + self.class.settings[:width]) + else + obj = debug_eval(@match.post_match) + unless obj.kind_of? Module + print "Should be Class/Module: %s\n", @match.post_match + else + print "%s\n", columnize(obj.instance_methods(false).sort(), + self.class.settings[:width]) + end + end + end + + class << self + def help_command + 'method' + end + + def help(cmd) + %{ + m[ethod] i[nstance] \tshow methods of object + m[ethod] iv \t\tshow instance variables of object + m[ethod] \t\tshow instance methods of class or module + } + end + end + end + +end diff --git a/cli/ruby-debug/commands/.svn/text-base/quit.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/quit.rb.svn-base new file mode 100644 index 0000000..767fedb --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/quit.rb.svn-base @@ -0,0 +1,39 @@ +module Debugger + + # Implements debugger "quit" command + class QuitCommand < Command + self.allow_in_control = true + + def regexp + / ^\s* + (?:q(?:uit)?|exit) \s* + (!|\s+unconditionally)? \s* + $ + /ix + end + + def execute + if @match[1] or confirm("Really quit? (y/n) ") + @state.interface.finalize + exit! # exit -> exit!: No graceful way to stop threads... + end + end + + class << self + def help_command + %w[quit exit] + end + + def help(cmd) + %{ + q[uit] [!|unconditionally]\texit from debugger. + exit[!]\talias to quit + + Normally we prompt before exiting. However if the parameter + "unconditionally" or is given or suffixed with !, we stop + without asking further questions. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/reload.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/reload.rb.svn-base new file mode 100644 index 0000000..822d5e6 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/reload.rb.svn-base @@ -0,0 +1,40 @@ +module Debugger + # Implements debugger "reload" command. + class ReloadCommand < Command + self.allow_in_control = true + + register_setting_get(:reload_source_on_change) do + Debugger.reload_source_on_change + end + register_setting_set(:reload_source_on_change) do |value| + Debugger.reload_source_on_change = value + end + + def regexp + /^\s*r(?:eload)?$/ + end + + def execute + Debugger.source_reload + print "Source code is reloaded. Automatic reloading is #{source_reloading}.\n" + end + + private + + def source_reloading + Debugger.reload_source_on_change ? 'on' : 'off' + end + + class << self + def help_command + 'reload' + end + + def help(cmd) + %{ + r[eload]\tforces source code reloading + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/save.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/save.rb.svn-base new file mode 100644 index 0000000..d039201 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/save.rb.svn-base @@ -0,0 +1,90 @@ +module Debugger + module SaveFunctions # :nodoc: + + # Create a temporary file to write in if file is nil + def open_save + require "tempfile" + file = Tempfile.new("rdebug-save") + # We want close to not unlink, so redefine. + def file.close + @tmpfile.close if @tmpfile + end + return file + end + end + + class SaveCommand < Command # :nodoc: + self.allow_in_control = true + + def save_breakpoints(file) + Debugger.breakpoints.each do |b| + file.puts "break #{b.source}:#{b.pos}#{" if #{b.expr}" if b.expr}" + end + end + + def save_catchpoints(file) + Debugger.catchpoints.keys.each do |c| + file.puts "catch #{c}" + end + end + + def save_displays(file) + for d in @state.display + if d[0] + file.puts "display #{d[1]}" + end + end + end + + def save_settings(file) + # FIXME put routine in set + %w(autoeval basename debuggertesting).each do |setting| + on_off = show_onoff(Command.settings[setting.to_sym]) + file.puts "set #{setting} #{on_off}" + end + %w(autolist autoirb).each do |setting| + on_off = show_onoff(Command.settings[setting.to_sym] > 0) + file.puts "set #{setting} #{on_off}" + end + end + + def regexp + /^\s* sa(?:ve)? + (?:\s+(.+))? + \s*$/ix + end + + def execute + if not @match[1] or @match[1].strip.empty? + file = open_save() + else + file = open(@match[1], 'w') + end + save_breakpoints(file) + save_catchpoints(file) + # save_displays(file) + save_settings(file) + print "Saved to '#{file.path}'\n" + if @state and @state.interface + @state.interface.restart_file = file.path + end + file.close + end + + class << self + def help_command + 'save' + end + + def help(cmd) + %{ +save [FILE] +Saves current debugger state to FILE as a script file. +This includes breakpoints, catchpoints, display expressions and some settings. +If no filename is given, we will fabricate one. + +Use the 'source' command in another debug session to restore them.} + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/set.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/set.rb.svn-base new file mode 100644 index 0000000..df9bcfb --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/set.rb.svn-base @@ -0,0 +1,237 @@ +module Debugger + # Implements debugger "set" command. + class SetCommand < Command + SubcmdStruct2=Struct.new(:name, :min, :is_bool, :short_help, + :long_help) unless defined?(SubcmdStruct2) + Subcommands = + [ + ['annotate', 2, false, + "Set annotation level", +"0 == normal; +2 == output annotated suitably for use by programs that control +ruby-debug."], + ['args', 2, false, + "Set argument list to give program being debugged when it is started", +"Follow this command with any number of args, to be passed to the program."], + ['autoeval', 4, true, + "Evaluate every unrecognized command"], + ['autolist', 4, true, + "Execute 'list' command on every breakpoint"], + ['autoirb', 4, true, + "Invoke IRB on every stop"], + ['autoreload', 4, true, + "Reload source code when changed"], + ['basename', 1, true, + "Report file basename only showing file names"], + ['callstyle', 2, false, + "Set how you want call parameters displayed"], + ['debuggertesting', 8, false, + "Used when testing the debugger"], + ['forcestep', 2, true, + "Make sure 'next/step' commands always move to a new line"], + ['fullpath', 2, true, + "Display full file names in frames"], + ['history', 2, false, + "Generic command for setting command history parameters", +"set history filename -- Set the filename in which to record the command history +set history save -- Set saving of the history record on exit +set history size -- Set the size of the command history"], + ['keep-frame-bindings', 1, true, + "Save frame binding on each call"], + ['linetrace+', 10, true, + "Set line execution tracing to show different lines"], + ['linetrace', 3, true, + "Set line execution tracing"], + ['listsize', 3, false, + "Set number of source lines to list by default"], +# ['post-mortem', 3, true, +# "Set whether we do post-mortem handling on an uncaught exception"], + ['trace', 1, true, + "Display stack trace when 'eval' raises exception"], + ['width', 1, false, + "Number of characters the debugger thinks are in a line"], + ].map do |name, min, is_bool, short_help, long_help| + SubcmdStruct2.new(name, min, is_bool, short_help, long_help) + end unless defined?(Subcommands) + + self.allow_in_control = true + + def regexp + /^set (?: \s+ (.*) )?$/ix + end + + def execute + if not @match[1] + print "\"set\" must be followed by the name of an set command:\n" + print "List of set subcommands:\n\n" + for subcmd in Subcommands do + print "set #{subcmd.name} -- #{subcmd.short_help}\n" + end + else + args = @match[1].split(/[ \t]+/) + subcmd = args.shift + subcmd.downcase! + if subcmd =~ /^no/i + set_on = false + subcmd = subcmd[2..-1] + else + set_on = true + end + for try_subcmd in Subcommands do + if (subcmd.size >= try_subcmd.min) and + (try_subcmd.name[0..subcmd.size-1] == subcmd) + begin + if try_subcmd.is_bool + if args.size > 0 + set_on = get_onoff(args[0]) + end + end + case try_subcmd.name + when /^annotate$/ + level = get_int(args[0], "Set annotate", 0, 3, 0) + if level + Debugger.annotate = level + else + return + end + if defined?(Debugger::RDEBUG_SCRIPT) + # rdebug was called initially. 1st arg is script name. + Command.settings[:argv][1..-1] = args + else + # rdebug wasn't called initially. 1st arg is not script name. + Command.settings[:argv] = args + end + when /^args$/ + Command.settings[:argv][1..-1] = args + when /^autolist$/ + Command.settings[:autolist] = (set_on ? 1 : 0) + when /^autoeval$/ + Command.settings[:autoeval] = set_on + when /^basename$/ + Command.settings[:basename] = set_on + when /^callstyle$/ + if args[0] + arg = args[0].downcase.to_sym + case arg + when :short, :last, :tracked + Command.settings[:callstyle] = arg + Debugger.track_frame_args = arg == :tracked ? true : false + print "%s\n" % show_setting(try_subcmd.name) + return + end + end + print "Invalid call style #{arg}. Should be one of: " + + "'short', 'last', or 'tracked'.\n" + when /^trace$/ + Command.settings[:stack_trace_on_error] = set_on + when /^fullpath$/ + Command.settings[:full_path] = set_on + when /^autoreload$/ + Command.settings[:reload_source_on_change] = set_on + when /^autoirb$/ + Command.settings[:autoirb] = (set_on ? 1 : 0) + when /^debuggertesting$/ + Command.settings[:debuggertesting] = set_on + if set_on + Command.settings[:basename] = true + end + when /^forcestep$/ + self.class.settings[:force_stepping] = set_on + when /^history$/ + if 2 == args.size + interface = @state.interface + case args[0] + when /^save$/ + interface.history_save = get_onoff(args[1]) + when /^size$/ + interface.history_length = get_int(args[1], + "Set history size") + else + print "Invalid history parameter #{args[0]}. Should be 'save' or 'size'.\n" + end + else + print "Need two parameters for 'set history'; got #{args.size}.\n" + return + end + when /^keep-frame-bindings$/ + Debugger.keep_frame_binding = set_on + when /^linetrace\+$/ + self.class.settings[:tracing_plus] = set_on + when /^linetrace$/ + Debugger.tracing = set_on + when /^listsize$/ + listsize = get_int(args[0], "Set listsize", 1, nil, 10) + if listsize + self.class.settings[:listsize] = listsize + else + return + end +# when /^post-mortem$/ +# unless Debugger.post_mortem? == set_on +# if set_on +# Debugger.post_mortem +# else +# errmsg "Can't turn off post-mortem once it is on.\n" +# return +# end +# end + when /^width$/ + width = get_int(args[0], "Set width", 10, nil, 80) + if width + self.class.settings[:width] = width + ENV['COLUMNS'] = width.to_s + else + return + end + else + print "Unknown setting #{@match[1]}.\n" + return + end + print "%s\n" % show_setting(try_subcmd.name) + return + rescue RuntimeError + return + end + end + end + print "Unknown set command #{subcmd}\n" + end + end + + class << self + def help_command + "set" + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + str += "\n" + subcmd.long_help if subcmd.long_help + return str + else + return "Invalid 'set' subcommand '#{args[1]}'." + end + end + s = %{ + Modifies parts of the ruby-debug environment. Boolean values take + on, off, 1 or 0. + You can see these environment settings with the \"show\" command. + + -- + List of set subcommands: + -- + } + for subcmd in Subcommands do + s += "set #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/show.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/show.rb.svn-base new file mode 100644 index 0000000..f2992ad --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/show.rb.svn-base @@ -0,0 +1,253 @@ +module Debugger + # Mix-in module to showing settings + module ShowFunctions # :nodoc: + def show_setting(setting_name) + case setting_name + when /^annotate$/ + Debugger.annotate ||= 0 + return ("Annotation level is #{Debugger.annotate}") + when /^args$/ + if Command.settings[:argv] and Command.settings[:argv].size > 0 + if defined?(Debugger::RDEBUG_SCRIPT) + # rdebug was called initially. 1st arg is script name. + args = Command.settings[:argv][1..-1].join(' ') + else + # rdebug wasn't called initially. 1st arg is not script name. + args = Command.settings[:argv].join(' ') + end + else + args = '' + end + return "Argument list to give program being debugged when it is started is \"#{args}\"." + when /^autolist$/ + on_off = Command.settings[:autolist] > 0 + return "autolist is #{show_onoff(on_off)}." + when /^autoeval$/ + on_off = Command.settings[:autoeval] + return "autoeval is #{show_onoff(on_off)}." + when /^autoreload$/ + on_off = Command.settings[:reload_source_on_change] + return "autoreload is #{show_onoff(on_off)}." + when /^autoirb$/ + on_off = Command.settings[:autoirb] > 0 + return "autoirb is #{show_onoff(on_off)}." + when /^basename$/ + on_off = Command.settings[:basename] + return "basename is #{show_onoff(on_off)}." + when /^callstyle$/ + style = Command.settings[:callstyle] + return "Frame call-display style is #{style}." + when /^commands(:?\s+(\d+))?$/ + if @state.interface.readline_support? + s = ''; + args = @match[1].split + if args[1] + first_line = args[1].to_i - 4 + last_line = first_line + 10 - 1 + if first_line > Readline::HISTORY.length + first_line = last_line = Readline::HISTORY.length + elsif first_line <= 0 + first_line = 1 + end + if last_line > Readline::HISTORY.length + last_line = Readline::HISTORY.length + end + i = first_line + commands = Readline::HISTORY.to_a[first_line..last_line] + else + if Readline::HISTORY.length > 10 + commands = Readline::HISTORY.to_a[-10..-1] + i = Readline::HISTORY.length - 10 + else + commands = Readline::HISTORY.to_a + i = 1 + end + end + commands.each do |cmd| + s += ("%5d %s\n" % [i, cmd]) + i += 1 + end + else + s='No readline suport' + end + return s + when /^debuggertesting$/ + on_off = Command.settings[:debuggertesting] + return "Currently testing the debugger is #{show_onoff(on_off)}." + when /^forcestep$/ + on_off = self.class.settings[:force_stepping] + return "force-stepping is #{show_onoff(on_off)}." + when /^fullpath$/ + on_off = Command.settings[:full_path] + return "Displaying frame's full file names is #{show_onoff(on_off)}." + when /^history(:?\s+(filename|save|size))?$/ + args = @match[1].split + interface = @state.interface + if args[1] + show_save = show_size = show_filename = false + prefix = false + if args[1] == "save" + show_save = true + elsif args[1] == "size" + show_size = true + elsif args[1] == "filename" + show_filename = true + end + else + show_save = show_size = show_filename = true + prefix = true + end + s = [] + if show_filename + msg = (prefix ? "filename: " : "") + + "The filename in which to record the command history is " + + "#{interface.histfile.inspect}" + s << msg + end + if show_save + msg = (prefix ? "save: " : "") + + "Saving of history save is #{show_onoff(interface.history_save)}." + s << msg + end + if show_size + msg = (prefix ? "size: " : "") + + "Debugger history size is #{interface.history_length}" + s << msg + end + return s.join("\n") + when /^keep-frame-bindings$/ + on_off = Debugger.keep_frame_binding? + return "keep-frame-bindings is #{show_onoff(on_off)}." + when /^linetrace$/ + on_off = Debugger.tracing + return "line tracing is #{show_onoff(on_off)}." + when /^linetrace\+$/ + on_off = Command.settings[:tracing_plus] + if on_off + return "line tracing style is different consecutive lines." + else + return "line tracing style is every line." + end + when /^listsize$/ + listlines = Command.settings[:listsize] + return "Number of source lines to list by default is #{listlines}." + when /^port$/ + return "server port is #{Debugger::PORT}." + when /^post-mortem$/ + on_off = Debugger.post_mortem? + return "post-mortem handling is #{show_onoff(on_off)}." + when /^trace$/ + on_off = Command.settings[:stack_trace_on_error] + return "Displaying stack trace is #{show_onoff(on_off)}." + when /^version$/ + return "ruby-debug #{Debugger::VERSION}" + when /^width$/ + return "width is #{self.class.settings[:width]}." + else + return "Unknown show subcommand #{setting_name}." + end + end + end + + # Implements debugger "show" command. + class ShowCommand < Command + + Subcommands = + [ + ['annotate', 2, "Show annotation level", +"0 == normal; 2 == output annotated suitably for use by programs that control +ruby-debug."], + ['args', 2, + "Show argument list to give program being debugged when it is started", +"Follow this command with any number of args, to be passed to the program."], + ['autoeval', 4, "Show if unrecognized command are evaluated"], + ['autolist', 4, "Show if 'list' commands is run on breakpoints"], + ['autoirb', 4, "Show if IRB is invoked on debugger stops"], + ['autoreload', 4, "Show if source code is reloaded when changed"], + ['basename', 1, "Show if basename used in reporting files"], + ['callstyle', 2, "Show paramater style used showing call frames"], + ['commands', 2, "Show the history of commands you typed", +"You can supply a command number to start with."], + ['forcestep', 1, "Show if sure 'next/step' forces move to a new line"], + ['fullpath', 2, "Show if full file names are displayed in frames"], + ['history', 2, "Generic command for showing command history parameters", +"show history filename -- Show the filename in which to record the command history +show history save -- Show saving of the history record on exit +show history size -- Show the size of the command history"], + ['keep-frame-bindings', 1, "Save frame binding on each call"], + ['linetrace', 3, "Show line execution tracing"], + ['linetrace+', 10, + "Show if consecutive lines should be different are shown in tracing"], + ['listsize', 3, "Show number of source lines to list by default"], + ['port', 3, "Show server port"], + ['post-mortem', 3, "Show whether we go into post-mortem debugging on an uncaught exception"], + ['trace', 1, + "Show if a stack trace is displayed when 'eval' raises exception"], + ['version', 1, + "Show what version of the debugger this is"], + ['width', 1, + "Show the number of characters the debugger thinks are in a line"], + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(Subcommands) + + self.allow_in_control = true + + def regexp + /^show (?: \s+ (.+) )?$/xi + end + + def execute + if not @match[1] + print "\"show\" must be followed by the name of an show command:\n" + print "List of show subcommands:\n\n" + for subcmd in Subcommands do + print "show #{subcmd.name} -- #{subcmd.short_help}\n" + end + else + args = @match[1].split(/[ \t]+/) + param = args.shift + subcmd = find(Subcommands, param) + if subcmd + print "%s\n" % show_setting(subcmd.name) + else + print "Unknown show command #{param}\n" + end + end + end + + class << self + def help_command + "show" + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + str += "\n" + subcmd.long_help if subcmd.long_help + return str + else + return "Invalid 'show' subcommand '#{args[1]}'." + end + end + s = " + Generic command for showing things about the debugger. + + -- + List of show subcommands: + -- + " + for subcmd in Subcommands do + s += "show #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/source.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/source.rb.svn-base new file mode 100644 index 0000000..a5e7179 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/source.rb.svn-base @@ -0,0 +1,36 @@ +module Debugger + # Implements debugger "source" command. + class SourceCommand < Command + self.allow_in_control = true + + def regexp + /^\s* so(?:urce)? \s+ (.+) $/x + end + + def execute + file = File.expand_path(@match[1]).strip + unless File.exist?(file) + errmsg "Command file '#{file}' is not found\n" + return + end + if @state and @state.interface + @state.interface.command_queue += File.open(file).readlines + else + Debugger.run_script(file, @state) + end + end + + class << self + def help_command + 'source' + end + + def help(cmd) + %{ + source FILE\texecutes a file containing debugger commands + } + end + end + end + +end diff --git a/cli/ruby-debug/commands/.svn/text-base/stepping.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/stepping.rb.svn-base new file mode 100644 index 0000000..5b1c3b2 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/stepping.rb.svn-base @@ -0,0 +1,81 @@ +module Debugger + # Mix-in module to assist in command parsing. + module SteppingFunctions # :nodoc: + def parse_stepping_args(command_name, match) + if match[1].nil? + force = Command.settings[:force_stepping] + elsif match[1] == '+' + force = true + elsif match[1] == '-' + force = false + end + steps = get_int(match[2], command_name, 1) + return [steps, force] + end + end + # Implements debugger "next" command. + class NextCommand < Command + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s* n(?:ext)? + ([+-])?(?:\s+(\S+))? + \s*$/x + end + + def execute + steps, force = parse_stepping_args("Next", @match) + return unless steps + @state.context.step_over steps, @state.frame_pos, force + @state.proceed + end + + class << self + def help_command + 'next' + end + + def help(cmd) + %{ + n[ext][+-]?[ nnn]\tstep over once or nnn times, + \t\t'+' forces to move to another line. + \t\t'-' is the opposite of '+' and disables the force_stepping setting. + } + end + end + end + + # Implements debugger "step" command. + class StepCommand < Command + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s* s(?:tep)? + ([+-])?(?:\s+(\S+))? + \s*$/x + end + + def execute + steps, force = parse_stepping_args("Step", @match) + return unless steps + @state.context.step(steps, force) + @state.proceed + end + + class << self + def help_command + 'step' + end + + def help(cmd) + %{ + s[tep][+-]?[ nnn]\tstep (into methods) once or nnn times + \t\t'+' forces to move to another line. + \t\t'-' is the opposite of '+' and disables the force_stepping setting. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/threads.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/threads.rb.svn-base new file mode 100644 index 0000000..c06c8bf --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/threads.rb.svn-base @@ -0,0 +1,189 @@ +module Debugger + module ThreadFunctions # :nodoc: + def display_context(c, show_top_frame=true) + c_flag = c.thread == Thread.current ? '+' : ' ' + c_flag = '$' if c.suspended? + d_flag = c.ignored? ? '!' : ' ' + print "%s%s", c_flag, d_flag + print "%d ", c.thnum + print "%s\t", c.thread.inspect + if c.stack_size > 0 and show_top_frame + print "%s:%d", c.frame_file(0), c.frame_line(0) + end + print "\n" + end + + def parse_thread_num(subcmd, arg) + if '' == arg + errmsg "'%s' needs a thread number\n" % subcmd + nil + else + thread_num = get_int(arg, "thread #{subcmd}", 1) + return nil unless thread_num + get_context(thread_num) + end + end + + def parse_thread_num_for_cmd(subcmd, arg) + c = parse_thread_num(subcmd, arg) + return nil unless c + case + when nil == c + errmsg "No such thread.\n" + when @state.context == c + errmsg "It's the current thread.\n" + when c.ignored? + errmsg "Can't #{subcmd} to the debugger thread #{arg}.\n" + else # Everything is okay + return c + end + return nil + end + end + + class ThreadListCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + /^\s*th(?:read)?\s+l(?:ist)?\s*$/ + end + + def execute + threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c| + display_context(c) + end + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] l[ist]\t\t\tlist all threads + } + end + end + end + + class ThreadStopCommand < Command # :nodoc: + self.allow_in_control = true + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s*th(?:read)?\s+stop\s*(\S*)\s*$/ + end + + def execute + c = parse_thread_num_for_cmd("thread stop", @match[1]) + return unless c + c.suspend + display_context(c) + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] stop \t\tstop thread nnn + } + end + end + end + + class ThreadResumeCommand < Command # :nodoc: + self.allow_in_post_mortem = false + self.allow_in_control = true + self.need_context = true + + def regexp + /^\s*th(?:read)?\s+resume\s*(\S*)\s*$/ + end + + def execute + c = parse_thread_num_for_cmd("thread resume", @match[1]) + return unless c + if !c.thread.stop? + print "Already running." + return + end + c.resume + display_context(c) + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] resume \t\tresume thread nnn + } + end + end + end + + # Thread switch Must come after "Thread resume" because "switch" is + # optional + + class ThreadSwitchCommand < Command # :nodoc: + self.allow_in_control = true + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s*th(?:read)?\s*(?:sw(?:itch)?)?\s+(\S+)\s*$/ + end + + def execute + c = parse_thread_num_for_cmd("thread switch", @match[1]) + return unless c + display_context(c) + c.stop_next = 1 + c.thread.run + @state.proceed + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] [sw[itch]] \tswitch thread context to nnn + } + end + end + end + + class ThreadCurrentCommand < Command # :nodoc: + self.need_context = true + + def regexp + /^\s*th(?:read)?\s*(?:cur(?:rent)?)?\s*$/ + end + + def execute + display_context(@state.context) + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] [cur[rent]]\t\tshow current thread + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/tmate.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/tmate.rb.svn-base new file mode 100644 index 0000000..060a7d1 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/tmate.rb.svn-base @@ -0,0 +1,36 @@ +module Debugger + if RUBY_PLATFORM =~ /darwin/ + class TextMateCommand < Command # :nodoc: + def regexp + /^\s*tm(?:ate)?(?:\s*(\d+))?$/ + end + + def execute + if @match[1] + frm_n = @match[1].to_i + if frm_n > @state.context.stack_size || frm_n == 0 + print "Wrong frame number\n" + return + end + file, line = @state.context.frame_file(frm_n-1), @state.context.frame_line(frm_n-1) + else + file, line = @state.file, @state.line + end + %x|open 'txmt://open?url=file://#{File.expand_path(file)}&line=#{line}'| + end + + class << self + def help_command + 'tmate' + end + + def help(cmd) + %{ + tm[ate] n\topens a current file in TextMate. + \t\tIt uses n-th frame if arg (n) is specifed. + } + end + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/trace.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/trace.rb.svn-base new file mode 100644 index 0000000..ed063aa --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/trace.rb.svn-base @@ -0,0 +1,57 @@ +module Debugger + class TraceCommand < Command # :nodoc: + def regexp + /^\s* tr(?:ace)? (?: \s+ (\S+)) # on |off | var(iable) + (?: \s+ (\S+))? # (all | variable-name)? + (?: \s+ (\S+))? \s* # (stop | nostop)? + $/ix + end + + def execute + if @match[1] =~ /on|off/ + onoff = 'on' == @match[1] + if @match[2] + Debugger.current_context.tracing = onoff + print "Tracing %s all threads.\n" % (onoff ? 'on' : 'off') + else + Debugger.tracing = onoff + print "Tracing %s on current thread.\n" % (onoff ? 'on' : 'off') + end + elsif @match[1] =~ /var(?:iable)?/ + varname=@match[2] + if debug_eval("defined?(#{varname})") + if @match[3] && @match[3] !~ /(:?no)?stop/ + errmsg("expecting 'stop' or 'nostop'; got %s\n" % @match[3]) + else + dbg_cmd = if @match[3] && (@match[3] !~ /nostop/) + 'debugger' else '' end + end + eval(" + trace_var(:#{varname}) do |val| + print \"traced variable #{varname} has value \#{val}\n\" + #{dbg_cmd} + end") + else + errmsg "#{varname} is not a global variable.\n" + end + else + errmsg("expecting 'on', 'off', 'var' or 'variable'; got: %s\n" % + @match[1]) + end + end + + class << self + def help_command + 'trace' + end + + def help(cmd) + %{ + tr[ace] (on|off)\tset trace mode of current thread + tr[ace] (on|off) all\tset trace mode of all threads + tr[ace] var(iable) VARNAME [stop|nostop]\tset trace variable on VARNAME + } + end + end + end +end diff --git a/cli/ruby-debug/commands/.svn/text-base/variables.rb.svn-base b/cli/ruby-debug/commands/.svn/text-base/variables.rb.svn-base new file mode 100644 index 0000000..e326e46 --- /dev/null +++ b/cli/ruby-debug/commands/.svn/text-base/variables.rb.svn-base @@ -0,0 +1,199 @@ +module Debugger + module VarFunctions # :nodoc: + def var_list(ary, b = get_binding) + ary.sort! + for v in ary + begin + s = debug_eval(v, b).inspect + rescue + begin + s = debug_eval(v, b).to_s + rescue + s = "*Error in evaluation*" + end + end + if s.size > self.class.settings[:width] + s[self.class.settings[:width]-3 .. -1] = "..." + end + print "%s = %s\n", v, s + end + end + def var_class_self + obj = debug_eval('self') + var_list(obj.class.class_variables, get_binding) + end + end + + # Implements the debugger 'var class' command. + class VarClassVarCommand < Command + def regexp + /^\s*v(?:ar)?\s+cl(?:ass)?/ + end + + def execute + unless @state.context + errmsg "can't get class variables here.\n" + return + end + var_class_self + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] cl[ass] \t\t\tshow class variables of self + } + end + end + end + + class VarConstantCommand < Command # :nodoc: + def regexp + /^\s*v(?:ar)?\s+co(?:nst(?:ant)?)?\s+/ + end + + def execute + obj = debug_eval(@match.post_match) + if obj.kind_of? Module + constants = debug_eval("#{@match.post_match}.constants") + constants.sort! + for c in constants + next if c =~ /SCRIPT/ + value = obj.const_get(c) rescue "ERROR: #{$!}" + print " %s => %p\n", c, value + end + else + print "Should be Class/Module: %s\n", @match.post_match + end + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] c[onst] \t\tshow constants of object + } + end + end + end + + class VarGlobalCommand < Command # :nodoc: + def regexp + /^\s*v(?:ar)?\s+g(?:lobal)?\s*$/ + end + + def execute + var_list(global_variables) + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] g[lobal]\t\t\tshow global variables + } + end + end + end + + class VarInstanceCommand < Command # :nodoc: + def regexp + /^\s*v(?:ar)?\s+ins(?:tance)?\s*/ + end + + def execute + obj = debug_eval(@match.post_match.empty? ? 'self' : @match.post_match) + var_list(obj.instance_variables, obj.instance_eval{binding()}) + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] i[nstance] \tshow instance variables of object + } + end + end + end + + # Implements the debugger 'var local' command. + class VarLocalCommand < Command + def regexp + /^\s*v(?:ar)?\s+l(?:ocal)?\s*$/ + end + + def execute + locals = @state.context.frame_locals(@state.frame_pos) + _self = @state.context.frame_self(@state.frame_pos) + locals.keys.sort.each do |name| + print " %s => %p\n", name, locals[name] + end + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] l[ocal]\t\t\tshow local variables + } + end + end + end + + # Implements the debugger 'var inherit' command. + begin + require 'classtree' + have_classtree = true + rescue LoadError + have_classtree = false + end + + class VarInheritCommand < Command + def regexp + /^\s*v(?:ar)?\s+ct\s*/ + end + + def execute + unless @state.context + errmsg "can't get object inheritance.\n" + return + end + puts @match.post_match + obj = debug_eval("#{@match.post_match}.classtree") + if obj + print obj + else + errmsg "Trouble getting object #{@match.post_match}\n" + end + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] ct\t\t\tshow class heirarchy of object + } + end + end + end if have_classtree + +end diff --git a/cli/ruby-debug/commands/breakpoints.rb b/cli/ruby-debug/commands/breakpoints.rb new file mode 100644 index 0000000..d3b9901 --- /dev/null +++ b/cli/ruby-debug/commands/breakpoints.rb @@ -0,0 +1,153 @@ +module Debugger + + # Implements debugger "break" command. + class AddBreakpoint < Command + self.allow_in_control = true + + def regexp + / ^\s* + b(?:reak)? + (?: \s+ #{Position_regexp})? \s* + (?: \s+ (.*))? \s* + $ + /x + end + + def execute + if @match[1] + line, _, _, expr = @match.captures + else + _, file, line, expr = @match.captures + end + if expr + if expr !~ /^\s*if\s+(.+)/ + if file or line + errmsg "Expecting 'if' in breakpoint condition; got: #{expr}.\n" + else + errmsg "Invalid breakpoint location: #{expr}.\n" + end + return + else + expr = $1 + end + end + + brkpt_filename = nil + if file.nil? + unless @state.context + errmsg "We are not in a state that has an associated file.\n" + return + end + brkpt_filename = @state.file + file = File.basename(@state.file) + if line.nil? + # Set breakpoint at current line + line = @state.line.to_s + end + elsif line !~ /^\d+$/ + # See if "line" is a method/function name + klass = debug_silent_eval(file) + if klass && klass.kind_of?(Module) + class_name = klass.name if klass + else + errmsg "Unknown class #{file}.\n" + throw :debug_error + end + else + # FIXME: This should be done in LineCache. + file = File.expand_path(file) if file.index(File::SEPARATOR) || \ + File::ALT_SEPARATOR && file.index(File::ALT_SEPARATOR) + brkpt_filename = file + end + + if line =~ /^\d+$/ + line = line.to_i + if LineCache.cache(brkpt_filename, Command.settings[:reload_source_on_change]) + last_line = LineCache.size(brkpt_filename) + if line > last_line + errmsg("There are only %d lines in file \"%s\".\n", last_line, file) + return + end + unless LineCache.trace_line_numbers(brkpt_filename).member?(line) + errmsg("Line %d is not a stopping point in file \"%s\".\n", line, file) + return + end + else + errmsg("No source file named %s\n" % file) + return unless confirm("Set breakpoint anyway? (y/n) ") + end + + unless @state.context + errmsg "We are not in a state we can add breakpoints.\n" + return + end + b = Debugger.add_breakpoint brkpt_filename, line, expr + print "Breakpoint %d file %s, line %s\n", b.id, brkpt_filename, line.to_s + unless syntax_valid?(expr) + errmsg("Expression \"#{expr}\" syntactically incorrect; breakpoint disabled.\n") + b.enabled = false + end + else + method = line.intern.id2name + b = Debugger.add_breakpoint class_name, method, expr + print "Breakpoint %d at %s::%s\n", b.id, class_name, method.to_s + end + end + + class << self + def help_command + 'break' + end + + def help(cmd) + %{ + b[reak] file:line [if expr] + b[reak] class(.|#)method [if expr] + \tset breakpoint to some position, (optionally) if expr == true + } + end + end + end + + # Implements debugger "delete" command. + class DeleteBreakpointCommand < Command + self.allow_in_control = true + + def regexp + /^\s *del(?:ete)? (?:\s+(.*))?$/ix + end + + def execute + unless @state.context + errmsg "We are not in a state we can delete breakpoints.\n" + return + end + brkpts = @match[1] + unless brkpts + if confirm("Delete all breakpoints? (y or n) ") + Debugger.breakpoints.clear + end + else + brkpts.split(/[ \t]+/).each do |pos| + pos = get_int(pos, "Delete", 1) + return unless pos + unless Debugger.remove_breakpoint(pos) + errmsg "No breakpoint number %d\n", pos + end + end + end + end + + class << self + def help_command + 'delete' + end + + def help(cmd) + %{ + del[ete][ nnn...]\tdelete some or all breakpoints + } + end + end + end +end diff --git a/cli/ruby-debug/commands/catchpoint.rb b/cli/ruby-debug/commands/catchpoint.rb new file mode 100644 index 0000000..964f6ab --- /dev/null +++ b/cli/ruby-debug/commands/catchpoint.rb @@ -0,0 +1,55 @@ +module Debugger + class CatchCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + /^\s* cat(?:ch)? + (?:\s+ (\S+))? + (?:\s+ (off))? \s* $/ix + end + + def execute + excn = @match[1] + if not excn + # No args given. + info_catch + elsif not @match[2] + # One arg given. + if 'off' == excn + Debugger.catchpoints.clear if + confirm("Delete all catchpoints? (y or n) ") + else + binding = @state.context ? get_binding : TOPLEVEL_BINDING + unless debug_eval("#{excn}.is_a?(Class)", binding) + print "Warning #{excn} is not known to be a Class\n" + end + Debugger.add_catchpoint(excn) + print "Catch exception %s.\n", excn + end + elsif @match[2] != 'off' + errmsg "Off expected. Got %s\n", @match[2] + elsif Debugger.catchpoints.member?(excn) + Debugger.catchpoints.delete(excn) + print "Catch for exception %s removed.\n", excn + else + errmsg "Catch for exception %s not found.\n", excn + end + end + + class << self + def help_command + 'catch' + end + + def help(cmd) + %{ + cat[ch]\t\tsame as "info catch" + cat[ch] [on|off] +\tIntercept when there would otherwise be no handler. +\tWith an "on" or "off", turn handling the exception on or off. + cat[ch] off\tdelete all catchpoints + } + end + end + end +end diff --git a/cli/ruby-debug/commands/condition.rb b/cli/ruby-debug/commands/condition.rb new file mode 100644 index 0000000..322812e --- /dev/null +++ b/cli/ruby-debug/commands/condition.rb @@ -0,0 +1,49 @@ +module Debugger + + class ConditionCommand < Command # :nodoc: + + def regexp + /^\s* cond(?:ition)? (?:\s+(\d+)\s*(.*))?$/ix + end + + def execute + if not @match[1] + errmsg "\"condition\" must be followed a breakpoint number and expression\n" + else + breakpoints = Debugger.breakpoints.sort_by{|b| b.id } + largest = breakpoints.inject(0) do |largest, b| + largest = b.id if b.id > largest + end + if 0 == largest + print "No breakpoints have been set.\n" + return + end + pos = get_int(@match[1], "Condition", 1, largest) + return unless pos + breakpoints.each do |b| + if b.id == pos + b.expr = @match[2].empty? ? nil : @match[2] + break + end + end + + end + end + + class << self + def help_command + 'condition' + end + + def help(cmd) + %{ + Condition breakpoint-number expression +Specify breakpoint number N to break only if COND is true. +N is an integer and COND is an expression to be evaluated whenever +breakpoint N is reached. If the empty string is used, the condition is removed. + } + end + end + end + +end # module Debugger diff --git a/cli/ruby-debug/commands/continue.rb b/cli/ruby-debug/commands/continue.rb new file mode 100644 index 0000000..5bee4b3 --- /dev/null +++ b/cli/ruby-debug/commands/continue.rb @@ -0,0 +1,38 @@ +module Debugger + + # Implements debugger "continue" command. + class ContinueCommand < Command + self.allow_in_post_mortem = true + self.need_context = false + def regexp + /^\s* c(?:ont(?:inue)?)? (?:\s+(.*))? $/x + end + + def execute + if @match[1] && !@state.context.dead? + filename = File.expand_path(@state.file) + line_number = get_int(@match[1], "Continue", 0, nil, 0) + return unless line_number + unless LineCache.trace_line_numbers(filename).member?(line_number) + errmsg("Line %d is not a stopping point in file \"%s\".\n", + line_number, filename) + return + end + @state.context.set_breakpoint(filename, line_number) + end + @state.proceed + end + + class << self + def help_command + 'continue' + end + + def help(cmd) + %{ + c[ont[inue]][ nnn]\trun until program ends, hits a breakpoint or reaches line nnn + } + end + end + end +end diff --git a/cli/ruby-debug/commands/control.rb b/cli/ruby-debug/commands/control.rb new file mode 100644 index 0000000..78e11b5 --- /dev/null +++ b/cli/ruby-debug/commands/control.rb @@ -0,0 +1,107 @@ +module Debugger + class RestartCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + / ^\s* + (?:restart|R) + (?:\s+ (\S?.*\S))? \s* + $ + /ix + end + + def execute + if not defined? Debugger::PROG_SCRIPT + errmsg "Don't know name of debugged program\n" + return + end + prog_script = Debugger::PROG_SCRIPT + if not defined? Debugger::RDEBUG_SCRIPT + # FIXME? Should ask for confirmation? + print "Debugger was not called from the outset...\n" + rdebug_script = prog_script + else + rdebug_script = Debugger::RDEBUG_SCRIPT + end + begin + Dir.chdir(Debugger::INITIAL_DIR) + rescue + print "Failed to change initial directory #{Debugger::INITIAL_DIR}" + end + if not File.exist?(File.expand_path(prog_script)) + errmsg "Ruby program #{prog_script} doesn't exist\n" + return + end + if not File.executable?(prog_script) and rdebug_script == prog_script + print "Ruby program #{prog_script} doesn't seem to be executable...\n" + print "We'll add a call to Ruby.\n" + ruby = begin defined?(Gem) ? Gem.ruby : "ruby" rescue "ruby" end + rdebug_script = "#{ruby} -I#{$:.join(' -I')} #{prog_script}" + else + rdebug_script += ' ' + end + if @match[1] + argv = [prog_script] + @match[1].split(/[ \t]+/) + else + if not defined? Command.settings[:argv] + errmsg "Arguments have not been set. Use 'set args' to set them.\n" + return + else + argv = Command.settings[:argv] + end + end + args = argv.join(' ') + + # An execv would be preferable to the "exec" below. + cmd = rdebug_script + args + print "Re exec'ing:\n\t#{cmd}\n" + exec cmd + rescue Errno::EOPNOTSUPP + print "Restart command is not available at this time.\n" + end + + class << self + def help_command + 'restart' + end + + def help(cmd) + %{ + restart|R [args] + Restart the program. This is is a re-exec - all debugger state + is lost. If command arguments are passed those are used. + } + end + end + end + + class InterruptCommand < Command # :nodoc: + self.allow_in_control = true + self.allow_in_post_mortem = false + self.event = false + self.need_context = true + + def regexp + /^\s*i(?:nterrupt)?\s*$/ + end + + def execute + unless Debugger.interrupt_last + context = Debugger.thread_context(Thread.main) + context.interrupt + end + end + + class << self + def help_command + 'interrupt' + end + + def help(cmd) + %{ + i[nterrupt]\tinterrupt the program + } + end + end + end +end diff --git a/cli/ruby-debug/commands/display.rb b/cli/ruby-debug/commands/display.rb new file mode 100644 index 0000000..ff82079 --- /dev/null +++ b/cli/ruby-debug/commands/display.rb @@ -0,0 +1,120 @@ +module Debugger + module DisplayFunctions # :nodoc: + def display_expression(exp) + print "%s = %s\n", exp, debug_silent_eval(exp).to_s + end + + def active_display_expressions? + @state.display.select{|d| d[0]}.size > 0 + end + + def print_display_expressions + n = 1 + for d in @state.display + if d[0] + print "%d: ", n + display_expression(d[1]) + end + n += 1 + end + end + end + + class AddDisplayCommand < Command # :nodoc: + def regexp + /^\s*disp(?:lay)?\s+(.+)$/ + end + + def execute + exp = @match[1] + @state.display.push [true, exp] + print "%d: ", @state.display.size + display_expression(exp) + end + + class << self + def help_command + 'display' + end + + def help(cmd) + %{ + disp[lay] \tadd expression into display expression list + } + end + end + end + + class DisplayCommand < Command # :nodoc: + def self.always_run + Debugger.annotate = 0 unless Debugger.annotate + if Debugger.annotate > 1 + 0 + else + 2 + end + end + + def regexp + /^\s*disp(?:lay)?$/ + end + + def execute + print_display_expressions + end + + class << self + def help_command + 'display' + end + + def help(cmd) + %{ + disp[lay]\t\tdisplay expression list + } + end + end + end + + class DeleteDisplayCommand < Command # :nodoc: + + def regexp + /^\s* undisp(?:lay)? \s* (?:(\S+))?$/x + end + + def execute + unless pos = @match[1] + if confirm("Clear all expressions? (y/n) ") + for d in @state.display + d[0] = false + end + end + else + pos = get_int(pos, "Undisplay") + return unless pos + if @state.display[pos-1] + @state.display[pos-1][0] = nil + else + errmsg "Display expression %d is not defined.\n", pos + end + end + end + + class << self + def help_command + 'undisplay' + end + + def help(cmd) + %{ + undisp[lay][ nnn] + Cancel some expressions to be displayed when program stops. + Arguments are the code numbers of the expressions to stop displaying. + No argument means cancel all automatic-display expressions. + "delete display" has the same effect as this command. + Do "info display" to see current list of code numbers. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/edit.rb b/cli/ruby-debug/commands/edit.rb new file mode 100644 index 0000000..ae12887 --- /dev/null +++ b/cli/ruby-debug/commands/edit.rb @@ -0,0 +1,48 @@ +module Debugger + class Edit < Command # :nodoc: + self.allow_in_control = true + def regexp + /^\s* ed(?:it)? (?:\s+(.*))?$/ix + end + + def execute + if not @match[1] or @match[1].strip.empty? + unless @state.context + errmsg "We are not in a state that has an associated file.\n" + return + end + file = @state.file + line_number = @state.line + elsif @pos_match = /([^:]+)[:]([0-9]+)/.match(@match[1]) + file, line_number = @pos_match.captures + else + errmsg "Invalid file/line number specification: #{@match[1]}\n" + return + end + editor = ENV['EDITOR'] || 'ex' + if File.readable?(file) + system("#{editor} +#{line_number} #{file}") + else + errmsg "File \"#{file}\" is not readable.\n" + end + end + + class << self + def help_command + 'edit' + end + + def help(cmd) + %{ + Edit specified file. + +With no argument, edits file containing most recent line listed. +Editing targets can also be specified in this: + FILE:LINENUM, to edit at that line in that file, + } + end + end + end + + +end # module Debugger diff --git a/cli/ruby-debug/commands/enable.rb b/cli/ruby-debug/commands/enable.rb new file mode 100644 index 0000000..d70f343 --- /dev/null +++ b/cli/ruby-debug/commands/enable.rb @@ -0,0 +1,202 @@ +module Debugger + # Mix-in module to assist in command parsing. + module EnableDisableFunctions # :nodoc: + def enable_disable_breakpoints(is_enable, args) + breakpoints = Debugger.breakpoints.sort_by{|b| b.id } + largest = breakpoints.inject(0) do |largest, b| + largest = b.id if b.id > largest + end + if 0 == largest + errmsg "No breakpoints have been set.\n" + return + end + args.each do |pos| + pos = get_int(pos, "#{is_enable} breakpoints", 1, largest) + return nil unless pos + breakpoints.each do |b| + if b.id == pos + enabled = ("Enable" == is_enable) + if enabled + unless syntax_valid?(b.expr) + errmsg("Expression \"#{b.expr}\" syntactically incorrect; breakpoint remains disabled.\n") + break + end + end + b.enabled = ("Enable" == is_enable) + break + end + end + end + end + + def enable_disable_display(is_enable, args) + if 0 == @state.display.size + errmsg "No display expressions have been set.\n" + return + end + args.each do |pos| + pos = get_int(pos, "#{is_enable} display", 1, @state.display.size) + return nil unless pos + @state.display[pos-1][0] = ("Enable" == is_enable) + end + end + + end + + class EnableCommand < Command # :nodoc: + Subcommands = + [ + ['breakpoints', 2, "Enable specified breakpoints", +"Give breakpoint numbers (separated by spaces) as arguments. +This is used to cancel the effect of the \"disable\" command." + ], + ['display', 2, + "Enable some expressions to be displayed when program stops", +"Arguments are the code numbers of the expressions to resume displaying. +Do \"info display\" to see current list of code numbers."], + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(Subcommands) + + def regexp + /^\s* en(?:able)? (?:\s+(.*))?$/ix + end + + def execute + if not @match[1] + errmsg "\"enable\" must be followed \"display\", \"breakpoints\"" + + " or breakpoint numbers.\n" + else + args = @match[1].split(/[ \t]+/) + param = args.shift + subcmd = find(Subcommands, param) + if subcmd + send("enable_#{subcmd.name}", args) + else + send("enable_breakpoints", args.unshift(param)) + end + end + end + + def enable_breakpoints(args) + enable_disable_breakpoints("Enable", args) + end + + def enable_display(args) + enable_disable_display("Enable", args) + end + + class << self + def help_command + 'enable' + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + str += "\n" + subcmd.long_help if subcmd.long_help + return str + else + return "Invalid 'enable' subcommand '#{args[1]}'." + end + end + s = %{ + Enable some things. + This is used to cancel the effect of the "disable" command. + -- + List of enable subcommands: + -- + } + for subcmd in Subcommands do + s += "enable #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end + + class DisableCommand < Command # :nodoc: + Subcommands = + [ + ['breakpoints', 1, "Disable some breakpoints", +"Arguments are breakpoint numbers with spaces in between. +A disabled breakpoint is not forgotten, but has no effect until reenabled."], + ['display', 1, "Disable some display expressions when program stops", +"Arguments are the code numbers of the expressions to stop displaying. +Do \"info display\" to see current list of code numbers."], + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(Subcommands) + + def regexp + /^\s* dis(?:able)? (?:\s+(.*))?$/ix + end + + def execute + if not @match[1] + errmsg "\"disable\" must be followed \"display\", \"breakpoints\"" + + " or breakpoint numbers.\n" + else + args = @match[1].split(/[ \t]+/) + param = args.shift + subcmd = find(Subcommands, param) + if subcmd + send("disable_#{subcmd.name}", args) + else + send("disable_breakpoints", args.unshift(param)) + end + end + end + + def disable_breakpoints(args) + enable_disable_breakpoints("Disable", args) + end + + def disable_display(args) + enable_disable_display("Disable", args) + end + + class << self + def help_command + 'disable' + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + str += "\n" + subcmd.long_help if subcmd.long_help + return str + else + return "Invalid 'disable' subcommand '#{args[1]}'." + end + end + s = %{ + Disable some things. + + A disabled item is not forgotten, but has no effect until reenabled. + Use the "enable" command to have it take effect again. + -- + List of disable subcommands: + -- + } + for subcmd in Subcommands do + s += "disable #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end + +end # module Debugger diff --git a/cli/ruby-debug/commands/eval.rb b/cli/ruby-debug/commands/eval.rb new file mode 100644 index 0000000..f752047 --- /dev/null +++ b/cli/ruby-debug/commands/eval.rb @@ -0,0 +1,176 @@ +module Debugger + module EvalFunctions # :nodoc: + def run_with_binding + binding = @state.context ? get_binding : TOPLEVEL_BINDING + $__dbg_interface = @state.interface + eval(<<-EOC, binding) + __dbg_verbose_save=$VERBOSE; $VERBOSE=false + def dbg_print(*args) + $__dbg_interface.print(*args) + end + remove_method :puts if self.respond_to?(:puts) && + defined?(remove_method) + def dbg_puts(*args) + $__dbg_interface.print(*args) + $__dbg_interface.print("\n") + end + $VERBOSE=__dbg_verbose_save + EOC + yield binding + ensure + $__dbg_interface = nil + end + end + + class EvalCommand < Command # :nodoc: + self.allow_in_control = true + + register_setting_get(:autoeval) do + EvalCommand.unknown + end + register_setting_set(:autoeval) do |value| + EvalCommand.unknown = value + end + + def match(input) + @input = input + super + end + + def regexp + /^\s*(p|e(?:val)?)\s+/ + end + + def execute + expr = @match ? @match.post_match : @input + run_with_binding do |b| + print "%s\n", debug_eval(expr, b).inspect + end + end + + class << self + def help_command + %w|p eval| + end + + def help(cmd) + if cmd == 'p' + %{ + p expression\tevaluate expression and print its value + } + else + %{ + e[val] expression\tevaluate expression and print its value, + \t\t\talias for p. + * NOTE - to turn on autoeval, use 'set autoeval' + } + end + end + end + end + + class PPCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + /^\s*pp\s+/ + end + + def execute + out = StringIO.new + run_with_binding do |b| + PP.pp(debug_eval(@match.post_match, b), out) + end + print out.string + rescue + out.puts $!.message + end + + class << self + def help_command + 'pp' + end + + def help(cmd) + %{ + pp expression\tevaluate expression and pretty-print its value + } + end + end + end + + class PutLCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + /^\s*putl\s+/ + end + + def execute + out = StringIO.new + run_with_binding do |b| + vals = debug_eval(@match.post_match, b) + if vals.is_a?(Array) + vals = vals.map{|item| item.to_s} + print "%s\n", columnize(vals, self.class.settings[:width]) + else + PP.pp(vals, out) + print out.string + end + end + rescue + out.puts $!.message + end + + class << self + def help_command + 'putl' + end + + def help(cmd) + %{ + putl expression\t\tevaluate expression, an array, and columnize its value + } + end + end + end + + class PSCommand < Command # :nodoc: + self.allow_in_control = true + + include EvalFunctions + + def regexp + /^\s*ps\s+/ + end + + def execute + out = StringIO.new + run_with_binding do |b| + vals = debug_eval(@match.post_match, b) + if vals.is_a?(Array) + vals = vals.map{|item| item.to_s} + print "%s\n", columnize(vals.sort!, self.class.settings[:width]) + else + PP.pp(vals, out) + print out.string + end + end + rescue + out.puts $!.message + end + + class << self + def help_command + 'ps' + end + + def help(cmd) + %{ + ps expression\tevaluate expression, an array, sort, and columnize its value + } + end + end + end + +end diff --git a/cli/ruby-debug/commands/finish.rb b/cli/ruby-debug/commands/finish.rb new file mode 100644 index 0000000..c7b77ff --- /dev/null +++ b/cli/ruby-debug/commands/finish.rb @@ -0,0 +1,42 @@ +module Debugger + # Implements the debugger 'finish' command. + class FinishCommand < Command + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s*fin(?:ish)? (?:\s+(.*))?$/x + end + + def execute + max_frame = @state.context.stack_size - @state.frame_pos + if !@match[1] or @match[1].empty? + frame_pos = @state.frame_pos + else + frame_pos = get_int(@match[1], "Finish", 0, max_frame-1, 0) + return nil unless frame_pos + end + @state.context.stop_frame = frame_pos + @state.frame_pos = 0 + @state.proceed + end + + class << self + def help_command + 'finish' + end + + def help(cmd) + %{ + fin[ish] [frame-number]\tExecute until selected stack frame returns. + +If no frame number is given, we run until the currently selected frame +returns. The currently selected frame starts out the most-recent +frame or 0 if no frame positioning (e.g "up", "down" or "frame") has +been performed. If a frame number is given we run until that frame +returns. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/frame.rb b/cli/ruby-debug/commands/frame.rb new file mode 100644 index 0000000..f9b6f26 --- /dev/null +++ b/cli/ruby-debug/commands/frame.rb @@ -0,0 +1,301 @@ +module Debugger + # Mix-in module to assist in command parsing. + module FrameFunctions # :nodoc: + def adjust_frame(frame_pos, absolute, context=@state.context) + @state.frame_pos = 0 if context != @state.context + if absolute + if frame_pos < 0 + abs_frame_pos = context.stack_size + frame_pos + else + abs_frame_pos = frame_pos + end + else + abs_frame_pos = @state.frame_pos + frame_pos + end + + if abs_frame_pos >= context.stack_size then + errmsg "Adjusting would put us beyond the oldest (initial) frame.\n" + return + elsif abs_frame_pos < 0 then + errmsg "Adjusting would put us beyond the newest (innermost) frame.\n" + return + end + if @state.frame_pos != abs_frame_pos then + @state.previous_line = nil + @state.frame_pos = abs_frame_pos + end + + @state.file = context.frame_file(@state.frame_pos) + @state.line = context.frame_line(@state.frame_pos) + + print_frame(@state.frame_pos, true) + end + + def get_frame_call(prefix, pos, context) + id = context.frame_method(pos) + klass = context.frame_class(pos) + call_str = "" + if id + args = context.frame_args(pos) + locals = context.frame_locals(pos) + if Command.settings[:callstyle] != :short && klass + if Command.settings[:callstyle] == :tracked + arg_info = context.frame_args_info(pos) + end + call_str << "#{klass}." + end + call_str << id.id2name + if args.any? + call_str << "(" + args.each_with_index do |name, i| + case Command.settings[:callstyle] + when :short + call_str += "%s, " % [name] + when :last + klass = locals[name].class + if klass.inspect.size > 20+3 + klass = klass.inspect[0..20]+"..." + end + call_str += "%s#%s, " % [name, klass] + when :tracked + if arg_info && arg_info.size > i + call_str += "#{name}: #{arg_info[i].inspect}, " + else + call_str += "%s, " % name + end + end + if call_str.size > self.class.settings[:width] - prefix.size + # Strip off trailing ', ' if any but add stuff for later trunc + call_str[-2..-1] = ",...XX" + break + end + end + call_str[-2..-1] = ")" # Strip off trailing ', ' if any + end + end + return call_str + end + + def print_frame(pos, adjust = false, context=@state.context) + file = context.frame_file(pos) + line = context.frame_line(pos) + klass = context.frame_class(pos) + + unless Command.settings[:full_path] + path_components = file.split(/[\\\/]/) + if path_components.size > 3 + path_components[0...-3] = '...' + file = path_components.join(File::ALT_SEPARATOR || File::SEPARATOR) + end + end + + frame_num = "#%d " % pos + call_str = get_frame_call(frame_num, pos, context) + file_line = "at line %s:%d\n" % [CommandProcessor.canonic_file(file), line] + print frame_num + unless call_str.empty? + print call_str + print ' ' + if call_str.size + frame_num.size + file_line.size > self.class.settings[:width] + print "\n " + end + end + print file_line + if ENV['EMACS'] && adjust + fmt = (Debugger.annotate.to_i > 1 ? + "\032\032source %s:%d\n" : "\032\032%s:%d\n") + print fmt % [CommandProcessor.canonic_file(file), line] + end + end + + # Check if call stack is truncated. This can happen if + # Debugger.start is not called low enough in the call stack. An + # array of additional callstack lines from caller is returned if + # definitely truncated, false if not, and nil if we don't know. + # + # We determine truncation based on a passed in sentinal set via + # caller which can be nil. + # + # First we see if we can find our position in caller. If so, then + # we compare context position to that in caller using sentinal + # as a place to start ignoring additional caller entries. sentinal + # is set by rdebug, but if it's not set, i.e. nil then additional + # entries are presumably ones that we haven't recorded in context + def truncated_callstack?(context, sentinal=nil, cs=caller) + recorded_size = context.stack_size + to_find_fl = "#{context.frame_file(0)}:#{context.frame_line(0)}" + top_discard = false + cs.each_with_index do |fl, i| + fl.gsub!(/in `.*'$/, '') + fl.gsub!(/:$/, '') + if fl == to_find_fl + top_discard = i + break + end + end + if top_discard + cs = cs[top_discard..-1] + return false unless cs + return cs unless sentinal + if cs.size > recorded_size+2 && cs[recorded_size+2] != sentinal + # caller seems to truncate recursive calls and we don't. + # See if we can find sentinal in the first 0..recorded_size+1 entries + return false if cs[0..recorded_size+1].any?{ |f| f==sentinal } + return cs + end + return false + end + return nil + end + + + end + + # Implements debugger "where" or "backtrace" command. + class WhereCommand < Command + def regexp + /^\s*(?:w(?:here)?|bt|backtrace)$/ + end + + def execute + (0...@state.context.stack_size).each do |idx| + if idx == @state.frame_pos + print "--> " + else + print " " + end + print_frame(idx) + + end + if truncated_callstack?(@state.context, Debugger.start_sentinal) + print "Warning: saved frames may be incomplete; compare with caller(0).\n" + end + end + + class << self + def help_command + %w|where backtrace| + end + + def help(cmd) + s = if cmd == 'where' + %{ + w[here]\tdisplay stack frames + } + else + %{ + bt|backtrace\t\talias for where - display stack frames + } + end + s += %{ +Print the entire stack frame. Each frame is numbered, the most recent +frame is 0. frame number can be referred to in the "frame" command; +"up" and "down" add or subtract respectively to frame numbers shown. +The position of the current frame is marked with -->. } + end + end + end + + class UpCommand < Command # :nodoc: + def regexp + /^\s* u(?:p)? (?:\s+(.*))?$/x + end + + def execute + pos = get_int(@match[1], "Up") + return unless pos + adjust_frame(pos, false) + end + + class << self + def help_command + 'up' + end + + def help(cmd) + %{ + up[count]\tmove to higher frame + } + end + end + end + + class DownCommand < Command # :nodoc: + def regexp + /^\s* down (?:\s+(.*))? .*$/x + end + + def execute + pos = get_int(@match[1], "Down") + return unless pos + adjust_frame(-pos, false) + end + + class << self + def help_command + 'down' + end + + def help(cmd) + %{ + down[count]\tmove to lower frame + } + end + end + end + + class FrameCommand < Command # :nodoc: + def regexp + / ^\s* + f(?:rame)? + (?: \s+ (\S+))? \s* + (?: thread \s+ (.*))? \s* + $/x + end + + def execute + if not @match[1] + pos = 0 + else + pos = get_int(@match[1], "Frame") + return unless pos + end + if @match[2] + context = parse_thread_num('frame', @match[2]) + unless context + errmsg "Thread #{@match[2]} doesn't exist.\n" + return + end + else + context = @state.context + end + adjust_frame(pos, true, context) + end + + class << self + def help_command + 'frame' + end + + def help(cmd) + %{ + f[rame] [frame-number [thread thread-number]] + Move the current frame to the specified frame number, or the + 0 if no frame-number has been given. + + A negative number indicates position from the other end. So + 'frame -1' moves to the oldest frame, and 'frame 0' moves to + the newest frame. + + Without an argument, the command prints the current stack + frame. Since the current position is redisplayed, it may trigger a + resyncronization if there is a front end also watching over + things. + + If a thread number is given then we set the context for evaluating + expressions to that frame of that thread. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/help.rb b/cli/ruby-debug/commands/help.rb new file mode 100644 index 0000000..1144621 --- /dev/null +++ b/cli/ruby-debug/commands/help.rb @@ -0,0 +1,56 @@ +module Debugger + + # Implements debugger "help" command. + class HelpCommand < Command + self.allow_in_control = true + + def regexp + /^\s* h(?:elp)? (?:\s+(.+))? $/x + end + + def execute + if @match[1] + args = @match[1].split + cmds = @state.commands.select do |cmd| + [cmd.help_command].flatten.include?(args[0]) + end + else + args = @match[1] + cmds = [] + end + unless cmds.empty? + help = cmds.map{ |cmd| cmd.help(args) }.join + help = help.split("\n").map{|l| l.gsub(/^ +/, '')} + help.shift if help.first && help.first.empty? + help.pop if help.last && help.last.empty? + print help.join("\n") + else + if args and args[0] + errmsg "Undefined command: \"#{args[0]}\". Try \"help\"." + else + print "ruby-debug help v#{Debugger::VERSION}\n" unless + self.class.settings[:debuggertesting] + print "Type 'help ' for help on a specific command\n\n" + print "Available commands:\n" + cmds = @state.commands.map{ |cmd| cmd.help_command } + cmds = cmds.flatten.uniq.sort + print columnize(cmds, self.class.settings[:width]) + end + end + print "\n" + end + + class << self + def help_command + 'help' + end + + def help(cmd) + %{ + h[elp]\t\tprint this help + h[elp] command\tprint help on command + } + end + end + end +end diff --git a/cli/ruby-debug/commands/info.rb b/cli/ruby-debug/commands/info.rb new file mode 100644 index 0000000..3fac50c --- /dev/null +++ b/cli/ruby-debug/commands/info.rb @@ -0,0 +1,469 @@ +module Debugger + module InfoFunctions # :nodoc: + def info_catch(*args) + unless @state.context + print "No frame selected.\n" + return + end + if Debugger.catchpoints and not Debugger.catchpoints.empty? + # FIXME: show whether Exception is valid or not + # print "Exception: is_a?(Class)\n" + Debugger.catchpoints.each do |exception, hits| + # print "#{exception}: #{exception.is_a?(Class)}\n" + print "#{exception}\n" + end + else + print "No exceptions set to be caught.\n" + end + end + end + + # Implements debugger "info" command. + class InfoCommand < Command + self.allow_in_control = true + Subcommands = + [ + ['args', 1, 'Argument variables of current stack frame'], + ['breakpoints', 1, 'Status of user-settable breakpoints', + 'Without argument, list info about all breakpoints. With an +integer argument, list info on that breakpoint.'], + ['catch', 3, 'Exceptions that can be caught in the current stack frame'], + ['display', 2, 'Expressions to display when program stops'], + ['file', 4, 'Info about a particular file read in', +' +After the file name is supplied, you can list file attributes that +you wish to see. + +Attributes include: "all", "basic", "breakpoint", "lines", "mtime", "path" +and "sha1".'], + ['files', 5, 'File names and timestamps of files read in'], + ['global_variables', 2, 'Global variables'], + ['instance_variables', 2, + 'Instance variables of the current stack frame'], + ['line', 2, + 'Line number and file name of current position in source file'], + ['locals', 2, 'Local variables of the current stack frame'], + ['program', 2, 'Execution status of the program'], + ['stack', 2, 'Backtrace of the stack'], + ['thread', 6, 'List info about thread NUM', ' +If no thread number is given, we list info for all threads. \'terse\' and \'verbose\' +options are possible. If terse, just give summary thread name information. See +"help info threads" for more detail about this summary information. + +If \'verbose\' appended to the end of the command, then the entire +stack trace is given for each thread.'], + ['threads', 7, 'information of currently-known threads', ' +This information includes whether the thread is current (+), if it is +suspended ($), or ignored (!). The thread number and the top stack +item. If \'verbose\' is given then the entire stack frame is shown.'], + ['variables', 1, + 'Local and instance variables of the current stack frame'] + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(Subcommands) + + InfoFileSubcommands = + [ + ['all', 1, + 'All file information available - breakpoints, lines, mtime, path, and sha1'], + ['basic', 2, + 'basic information - path, number of lines'], + ['breakpoints', 2, 'Show trace line numbers', + 'These are the line number where a breakpoint can be set.'], + ['lines', 1, 'Show number of lines in the file'], + ['mtime', 1, 'Show modification time of file'], + ['path', 4, 'Show full file path name for file'], + ['sha1', 1, 'Show SHA1 hash of contents of the file'] + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(InfoFileSubcommands) + + InfoThreadSubcommands = + [ + ['terse', 1, 'summary information'], + ['verbose', 1, 'summary information and stack frame info'], + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(InfoThreadSubcommands) + + def regexp + /^\s* i(?:nfo)? (?:\s+(.*))?$/ix + end + + def execute + if @match[1].empty? + errmsg "\"info\" must be followed by the name of an info command:\n" + print "List of info subcommands:\n\n" + for subcmd in Subcommands do + print "info #{subcmd.name} -- #{subcmd.short_help}\n" + end + else + args = @match[1].split(/[ \t]+/) + param = args.shift + subcmd = find(Subcommands, param) + if subcmd + send("info_#{subcmd.name}", *args) + else + errmsg "Unknown info command #{param}\n" + end + end + end + + def info_args(*args) + unless @state.context + print "No frame selected.\n" + return + end + locals = @state.context.frame_locals(@state.frame_pos) + args = @state.context.frame_args(@state.frame_pos) + args.each do |name| + s = "#{name} = #{locals[name].inspect}" + if s.size > self.class.settings[:width] + s[self.class.settings[:width]-3 .. -1] = "..." + end + print "#{s}\n" + end + end + + def info_breakpoints(*args) + unless @state.context + print "info breakpoints not available here.\n" + return + end + unless Debugger.breakpoints.empty? + brkpts = Debugger.breakpoints.sort_by{|b| b.id} + unless args.empty? + a = args.map{|a| a.to_i} + brkpts = brkpts.select{|b| a.member?(b.id)} + if brkpts.empty? + errmsg "No breakpoints found among list given.\n" + return + end + end + print "Num Enb What\n" + brkpts.each do |b| + if b.expr.nil? + print "%3d %s at %s:%s\n", + b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos + else + print "%3d %s at %s:%s if %s\n", + b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos, b.expr + end + hits = b.hit_count + if hits > 0 + s = (hits > 1) ? 's' : '' + print "\tbreakpoint already hit #{hits} time#{s}\n" + end + end + else + print "No breakpoints.\n" + end + end + + def info_display(*args) + unless @state.context + print "info display not available here.\n" + return + end + if @state.display.find{|d| d[0]} + print "Auto-display expressions now in effect:\n" + print "Num Enb Expression\n" + n = 1 + for d in @state.display + print "%3d: %s %s\n", n, (d[0] ? 'y' : 'n'), d[1] if + d[0] != nil + n += 1 + end + else + print "There are no auto-display expressions now.\n" + end + end + + def info_file(*args) + unless args[0] + info_files + return + end + file = args[0] + param = args[1] + + param = 'basic' unless param + subcmd = find(InfoFileSubcommands, param) + unless subcmd + errmsg "Invalid parameter #{param}\n" + return + end + + unless LineCache::cached?(file) + unless LineCache::cached_script?(file) + print "File #{file} is not cached\n" + return + end + LineCache::cache(file, Command.settings[:reload_source_on_change]) + end + + print "File %s", file + path = LineCache.path(file) + if %w(all basic path).member?(subcmd.name) and path != file + print " - %s\n", path + else + print "\n" + end + + if %w(all basic lines).member?(subcmd.name) + lines = LineCache.size(file) + print "\t %d lines\n", lines if lines + end + + if %w(all breakpoints).member?(subcmd.name) + breakpoints = LineCache.trace_line_numbers(file) + if breakpoints + print "\tbreakpoint line numbers:\n" + print columnize(breakpoints.to_a.sort, self.class.settings[:width]) + end + end + + if %w(all mtime).member?(subcmd.name) + stat = LineCache.stat(file) + print "\t%s\n", stat.mtime if stat + end + if %w(all sha1).member?(subcmd.name) + print "\t%s\n", LineCache.sha1(file) + end + end + + def info_files(*args) + files = LineCache::cached_files + files += SCRIPT_LINES__.keys unless 'stat' == args[0] + files.uniq.sort.each do |file| + stat = LineCache::stat(file) + path = LineCache::path(file) + print "File %s", file + if path and path != file + print " - %s\n", path + else + print "\n" + end + print "\t%s\n", stat.mtime if stat + end + end + + def info_instance_variables(*args) + unless @state.context + print "info instance_variables not available here.\n" + return + end + obj = debug_eval('self') + var_list(obj.instance_variables) + end + + def info_line(*args) + unless @state.context + errmsg "info line not available here.\n" + return + end + print "Line %d of \"%s\"\n", @state.line, @state.file + end + + def info_locals(*args) + unless @state.context + errmsg "info line not available here.\n" + return + end + locals = @state.context.frame_locals(@state.frame_pos) + locals.keys.sort.each do |name| + ### FIXME: make a common routine + begin + s = "#{name} = #{locals[name].inspect}" + rescue + begin + s = "#{name} = #{locals[name].to_s}" + rescue + s = "*Error in evaluation*" + end + end + if s.size > self.class.settings[:width] + s[self.class.settings[:width]-3 .. -1] = "..." + end + print "#{s}\n" + end + end + + def info_program(*args) + if not @state.context + print "The program being debugged is not being run.\n" + return + elsif @state.context.dead? + print "The program crashed.\n" + if Debugger.last_exception + print("Exception: #{Debugger.last_exception.inspect}\n") + end + return + end + + print "Program stopped. " + case @state.context.stop_reason + when :step + print "It stopped after stepping, next'ing or initial start.\n" + when :breakpoint + print("It stopped at a breakpoint.\n") + when :catchpoint + print("It stopped at a catchpoint.\n") + when :catchpoint + print("It stopped at a catchpoint.\n") + else + print "unknown reason: %s\n" % @state.context.stop_reason.to_s + end + end + + def info_stack(*args) + if not @state.context + errmsg "info stack not available here.\n" + return + end + (0...@state.context.stack_size).each do |idx| + if idx == @state.frame_pos + print "--> " + else + print " " + end + print_frame(idx) + end + end + + def info_thread_preamble(arg) + if not @state.context + errmsg "info threads not available here.\n" + return false, false + end + verbose = if arg + subcmd = find(InfoThreadSubcommands, arg) + unless subcmd + errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n" + return false, false + end + 'verbose' == subcmd.name + else + false + end + return true, verbose + end + private :info_thread_preamble + + def info_threads(*args) + ok, verbose = info_thread_preamble(args[0]) + return unless ok + threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c| + display_context(c, !verbose) + if verbose and not c.ignored? + (0...c.stack_size).each do |idx| + print "\t" + print_frame(idx, false, c) + end + end + end + end + + def info_thread(*args) + unless args[0] + info_threads(args[0]) + return + end + ok, verbose = info_thread_preamble(args[1]) + return unless ok + c = parse_thread_num("info thread" , args[0]) + return unless c + display_context(c, !verbose) + if verbose and not c.ignored? + (0...c.stack_size).each do |idx| + print "\t" + print_frame(idx, false, c) + end + end + end + + def info_global_variables(*args) + unless @state.context + errmsg "info global_variables not available here.\n" + return + end + var_list(global_variables) + end + + def info_variables(*args) + if not @state.context + errmsg "info variables not available here.\n" + return + end + obj = debug_eval('self') + locals = @state.context.frame_locals(@state.frame_pos) + locals['self'] = @state.context.frame_self(@state.frame_pos) + locals.keys.sort.each do |name| + next if name =~ /^__dbg_/ # skip debugger pollution + ### FIXME: make a common routine + begin + s = "#{name} = #{locals[name].inspect}" + rescue + begin + s = "#{name} = #{locals[name].to_s}" + rescue + s = "#{name} = *Error in evaluation*" + end + end + if s.size > self.class.settings[:width] + s[self.class.settings[:width]-3 .. -1] = "..." + end + s.gsub!('%', '%%') # protect against printf format strings + print "#{s}\n" + end + var_list(obj.instance_variables, obj.instance_eval{binding()}) + var_class_self + end + + class << self + def help_command + 'info' + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + if 'file' == subcmd.name and args[2] + s = args[2] + subsubcmd = InfoFileSubcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subsubcmd + str += "\n" + subsubcmd.short_help + '.' + else + str += "\nInvalid file attribute #{args[2]}." + end + else + str += "\n" + subcmd.long_help if subcmd.long_help + end + return str + else + return "Invalid 'info' subcommand '#{args[1]}'." + end + end + s = %{ + Generic command for showing things about the program being debugged. + -- + List of info subcommands: + -- + } + for subcmd in Subcommands do + s += "info #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end +end diff --git a/cli/ruby-debug/commands/irb.rb b/cli/ruby-debug/commands/irb.rb new file mode 100644 index 0000000..2493e80 --- /dev/null +++ b/cli/ruby-debug/commands/irb.rb @@ -0,0 +1,123 @@ +require 'irb' + +module IRB # :nodoc: + module ExtendCommand # :nodoc: + class Continue # :nodoc: + def self.execute(conf) + throw :IRB_EXIT, :cont + end + end + class Next # :nodoc: + def self.execute(conf) + throw :IRB_EXIT, :next + end + end + class Step # :nodoc: + def self.execute(conf) + throw :IRB_EXIT, :step + end + end + end + ExtendCommandBundle.def_extend_command "cont", :Continue + ExtendCommandBundle.def_extend_command "n", :Next + ExtendCommandBundle.def_extend_command "step", :Step + + def self.start_session(binding) + unless @__initialized + args = ARGV.dup + ARGV.replace([]) + IRB.setup(nil) + ARGV.replace(args) + @__initialized = true + end + + workspace = WorkSpace.new(binding) + + irb = Irb.new(workspace) + + @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] + @CONF[:MAIN_CONTEXT] = irb.context + + catch(:IRB_EXIT) do + irb.eval_input + end + end +end + +module Debugger + + # Implements debugger "irb" command. + class IRBCommand < Command + + register_setting_get(:autoirb) do + IRBCommand.always_run + end + register_setting_set(:autoirb) do |value| + IRBCommand.always_run = value + end + + def regexp + /^\s* irb + (?:\s+(-d))? + \s*$/x + end + + def execute + unless @state.interface.kind_of?(LocalInterface) + print "Command is available only in local mode.\n" + throw :debug_error + end + + save_trap = trap("SIGINT") do + throw :IRB_EXIT, :cont if $rdebug_in_irb + end + + add_debugging = @match.is_a?(Array) && '-d' == @match[1] + $rdebug_state = @state if add_debugging + $rdebug_in_irb = true + cont = IRB.start_session(get_binding) + case cont + when :cont + @state.proceed + when :step + force = Command.settings[:force_stepping] + @state.context.step(1, force) + @state.proceed + when :next + force = Command.settings[:force_stepping] + @state.context.step_over(1, @state.frame_pos, force) + @state.proceed + else + file = @state.context.frame_file(0) + line = @state.context.frame_line(0) + CommandProcessor.print_location_and_text(file, line) + @state.previous_line = nil + end + + ensure + $rdebug_in_irb = nil + $rdebug_state = nil if add_debugging + trap("SIGINT", save_trap) if save_trap + end + + class << self + def help_command + 'irb' + end + + def help(cmd) + %{ + irb [-d]\tstarts an Interactive Ruby (IRB) session. + +If -d is added you can get access to debugger state via the global variable +$RDEBUG_state. + +irb is extended with methods "cont", "n" and "step" which +run the corresponding debugger commands. In contrast to the real debugger +commands these commands don't allow command arguments. + } + end + end + end +end + diff --git a/cli/ruby-debug/commands/kill.rb b/cli/ruby-debug/commands/kill.rb new file mode 100644 index 0000000..da5d05e --- /dev/null +++ b/cli/ruby-debug/commands/kill.rb @@ -0,0 +1,51 @@ +module Debugger + + # Implements debugger "kill" command + class KillCommand < Command + self.allow_in_control = true + + def regexp + / ^\s* + (?:kill) \s* + (?:\s+(\S+))?\s* + $ + /ix + end + + def execute + puts @match[1] + if @match[1] + signame = @match[1] + unless Signal.list.member?(signame) + errmsg("signal name #{signame} is not a signal I know about\n") + return false + end + if 'KILL' == signame: + @state.interface.finalize + end + else + if not confirm("Really kill? (y/n) ") + return + else + signame = 'KILL' + end + end + Process.kill(signame, Process.pid) + end + + class << self + def help_command + %w[kill] + end + + def help(cmd) + %{ + kill [SIGNAL] + + Send [signal] to Process.pid +Equivalent of Process.kill(Process.pid) + } + end + end + end +end diff --git a/cli/ruby-debug/commands/list.rb b/cli/ruby-debug/commands/list.rb new file mode 100644 index 0000000..165732f --- /dev/null +++ b/cli/ruby-debug/commands/list.rb @@ -0,0 +1,94 @@ +module Debugger + # Implements debugger "list" command. + class ListCommand < Command + + register_setting_get(:autolist) do + ListCommand.always_run + end + register_setting_set(:autolist) do |value| + ListCommand.always_run = value + end + + def regexp + /^\s* l(?:ist)? (?:\s*([-=])|\s+(.+))? $/x + end + + def execute + listsize = Command.settings[:listsize] + if !@match || !(@match[1] || @match[2]) + b = @state.previous_line ? + @state.previous_line + listsize : @state.line - (listsize/2) + e = b + listsize - 1 + elsif @match[1] == '-' + b = if @state.previous_line + if @state.previous_line > 0 + @state.previous_line - listsize + else + @state.previous_line + end + else + @state.line - (listsize/2) + end + e = b + listsize - 1 + elsif @match[1] == '=' + @state.previous_line = nil + b = @state.line - (listsize/2) + e = b + listsize -1 + else + b, e = @match[2].split(/[-,]/) + if e + b = b.to_i + e = e.to_i + else + b = b.to_i - (listsize/2) + e = b + listsize - 1 + end + end + @state.previous_line = display_list(b, e, @state.file, @state.line) + end + + class << self + def help_command + 'list' + end + + def help(cmd) + %{ + l[ist]\t\tlist forward + l[ist] -\tlist backward + l[ist] =\tlist current line + l[ist] nn-mm\tlist given lines + * NOTE - to turn on autolist, use 'set autolist' + } + end + end + + private + + # Show FILE from line B to E where CURRENT is the current line number. + # If we can show from B to E then we return B, otherwise we return the + # previous line @state.previous_line. + def display_list(b, e, file, current) + print "[%d, %d] in %s\n", b, e, file + lines = LineCache::getlines(file, + Command.settings[:reload_source_on_change]) + if lines + return @state.previous_line if b >= lines.size + e = lines.size if lines.size < e + [b, 1].max.upto(e) do |n| + if n > 0 && lines[n-1] + if n == current + print "=> %d %s\n", n, lines[n-1].chomp + else + print " %d %s\n", n, lines[n-1].chomp + end + end + end + else + errmsg "No sourcefile available for %s\n", file + return @state.previous_line + end + return e == lines.size ? @state.previous_line : b + end + end +end diff --git a/cli/ruby-debug/commands/method.rb b/cli/ruby-debug/commands/method.rb new file mode 100644 index 0000000..1d31ead --- /dev/null +++ b/cli/ruby-debug/commands/method.rb @@ -0,0 +1,84 @@ +module Debugger + + begin + require 'methodsig' + have_methodsig = true + rescue LoadError + have_methodsig = false + end + + # Implements the debugger 'method sig' command. + class MethodSigCommand < Command + def regexp + /^\s*m(?:ethod)?\s+sig(?:nature)?\s+(\S+)\s*$/ + end + + def execute + obj = debug_eval('method(:%s)' % @match[1]) + if obj.is_a?(Method) + begin + print "%s\n", obj.signature.to_s + rescue + errmsg("Can't get signature for '#{@match[1]}'\n") + end + else + errmsg("Can't make method out of '#{@match[1]}'\n") + end + end + + class << self + def help_command + 'method' + end + + def help(cmd) + %{ + m[ethod] sig[nature] \tshow the signature of a method + } + end + end + end if have_methodsig + + # Implements the debugger 'method' command. + class MethodCommand < Command + def regexp + /^\s*m(?:ethod)?\s+((iv)|(i(:?nstance\s+)?)\s+)?/ + end + + def execute + if @match[1] == "iv" + obj = debug_eval(@match.post_match) + obj.instance_variables.sort.each do |v| + print "%s = %s\n", v, obj.instance_variable_get(v).inspect + end + elsif @match[1] + obj = debug_eval(@match.post_match) + print "%s\n", columnize(obj.methods.sort(), + self.class.settings[:width]) + else + obj = debug_eval(@match.post_match) + unless obj.kind_of? Module + print "Should be Class/Module: %s\n", @match.post_match + else + print "%s\n", columnize(obj.instance_methods(false).sort(), + self.class.settings[:width]) + end + end + end + + class << self + def help_command + 'method' + end + + def help(cmd) + %{ + m[ethod] i[nstance] \tshow methods of object + m[ethod] iv \t\tshow instance variables of object + m[ethod] \t\tshow instance methods of class or module + } + end + end + end + +end diff --git a/cli/ruby-debug/commands/quit.rb b/cli/ruby-debug/commands/quit.rb new file mode 100644 index 0000000..767fedb --- /dev/null +++ b/cli/ruby-debug/commands/quit.rb @@ -0,0 +1,39 @@ +module Debugger + + # Implements debugger "quit" command + class QuitCommand < Command + self.allow_in_control = true + + def regexp + / ^\s* + (?:q(?:uit)?|exit) \s* + (!|\s+unconditionally)? \s* + $ + /ix + end + + def execute + if @match[1] or confirm("Really quit? (y/n) ") + @state.interface.finalize + exit! # exit -> exit!: No graceful way to stop threads... + end + end + + class << self + def help_command + %w[quit exit] + end + + def help(cmd) + %{ + q[uit] [!|unconditionally]\texit from debugger. + exit[!]\talias to quit + + Normally we prompt before exiting. However if the parameter + "unconditionally" or is given or suffixed with !, we stop + without asking further questions. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/reload.rb b/cli/ruby-debug/commands/reload.rb new file mode 100644 index 0000000..822d5e6 --- /dev/null +++ b/cli/ruby-debug/commands/reload.rb @@ -0,0 +1,40 @@ +module Debugger + # Implements debugger "reload" command. + class ReloadCommand < Command + self.allow_in_control = true + + register_setting_get(:reload_source_on_change) do + Debugger.reload_source_on_change + end + register_setting_set(:reload_source_on_change) do |value| + Debugger.reload_source_on_change = value + end + + def regexp + /^\s*r(?:eload)?$/ + end + + def execute + Debugger.source_reload + print "Source code is reloaded. Automatic reloading is #{source_reloading}.\n" + end + + private + + def source_reloading + Debugger.reload_source_on_change ? 'on' : 'off' + end + + class << self + def help_command + 'reload' + end + + def help(cmd) + %{ + r[eload]\tforces source code reloading + } + end + end + end +end diff --git a/cli/ruby-debug/commands/save.rb b/cli/ruby-debug/commands/save.rb new file mode 100644 index 0000000..d039201 --- /dev/null +++ b/cli/ruby-debug/commands/save.rb @@ -0,0 +1,90 @@ +module Debugger + module SaveFunctions # :nodoc: + + # Create a temporary file to write in if file is nil + def open_save + require "tempfile" + file = Tempfile.new("rdebug-save") + # We want close to not unlink, so redefine. + def file.close + @tmpfile.close if @tmpfile + end + return file + end + end + + class SaveCommand < Command # :nodoc: + self.allow_in_control = true + + def save_breakpoints(file) + Debugger.breakpoints.each do |b| + file.puts "break #{b.source}:#{b.pos}#{" if #{b.expr}" if b.expr}" + end + end + + def save_catchpoints(file) + Debugger.catchpoints.keys.each do |c| + file.puts "catch #{c}" + end + end + + def save_displays(file) + for d in @state.display + if d[0] + file.puts "display #{d[1]}" + end + end + end + + def save_settings(file) + # FIXME put routine in set + %w(autoeval basename debuggertesting).each do |setting| + on_off = show_onoff(Command.settings[setting.to_sym]) + file.puts "set #{setting} #{on_off}" + end + %w(autolist autoirb).each do |setting| + on_off = show_onoff(Command.settings[setting.to_sym] > 0) + file.puts "set #{setting} #{on_off}" + end + end + + def regexp + /^\s* sa(?:ve)? + (?:\s+(.+))? + \s*$/ix + end + + def execute + if not @match[1] or @match[1].strip.empty? + file = open_save() + else + file = open(@match[1], 'w') + end + save_breakpoints(file) + save_catchpoints(file) + # save_displays(file) + save_settings(file) + print "Saved to '#{file.path}'\n" + if @state and @state.interface + @state.interface.restart_file = file.path + end + file.close + end + + class << self + def help_command + 'save' + end + + def help(cmd) + %{ +save [FILE] +Saves current debugger state to FILE as a script file. +This includes breakpoints, catchpoints, display expressions and some settings. +If no filename is given, we will fabricate one. + +Use the 'source' command in another debug session to restore them.} + end + end + end +end diff --git a/cli/ruby-debug/commands/set.rb b/cli/ruby-debug/commands/set.rb new file mode 100644 index 0000000..df9bcfb --- /dev/null +++ b/cli/ruby-debug/commands/set.rb @@ -0,0 +1,237 @@ +module Debugger + # Implements debugger "set" command. + class SetCommand < Command + SubcmdStruct2=Struct.new(:name, :min, :is_bool, :short_help, + :long_help) unless defined?(SubcmdStruct2) + Subcommands = + [ + ['annotate', 2, false, + "Set annotation level", +"0 == normal; +2 == output annotated suitably for use by programs that control +ruby-debug."], + ['args', 2, false, + "Set argument list to give program being debugged when it is started", +"Follow this command with any number of args, to be passed to the program."], + ['autoeval', 4, true, + "Evaluate every unrecognized command"], + ['autolist', 4, true, + "Execute 'list' command on every breakpoint"], + ['autoirb', 4, true, + "Invoke IRB on every stop"], + ['autoreload', 4, true, + "Reload source code when changed"], + ['basename', 1, true, + "Report file basename only showing file names"], + ['callstyle', 2, false, + "Set how you want call parameters displayed"], + ['debuggertesting', 8, false, + "Used when testing the debugger"], + ['forcestep', 2, true, + "Make sure 'next/step' commands always move to a new line"], + ['fullpath', 2, true, + "Display full file names in frames"], + ['history', 2, false, + "Generic command for setting command history parameters", +"set history filename -- Set the filename in which to record the command history +set history save -- Set saving of the history record on exit +set history size -- Set the size of the command history"], + ['keep-frame-bindings', 1, true, + "Save frame binding on each call"], + ['linetrace+', 10, true, + "Set line execution tracing to show different lines"], + ['linetrace', 3, true, + "Set line execution tracing"], + ['listsize', 3, false, + "Set number of source lines to list by default"], +# ['post-mortem', 3, true, +# "Set whether we do post-mortem handling on an uncaught exception"], + ['trace', 1, true, + "Display stack trace when 'eval' raises exception"], + ['width', 1, false, + "Number of characters the debugger thinks are in a line"], + ].map do |name, min, is_bool, short_help, long_help| + SubcmdStruct2.new(name, min, is_bool, short_help, long_help) + end unless defined?(Subcommands) + + self.allow_in_control = true + + def regexp + /^set (?: \s+ (.*) )?$/ix + end + + def execute + if not @match[1] + print "\"set\" must be followed by the name of an set command:\n" + print "List of set subcommands:\n\n" + for subcmd in Subcommands do + print "set #{subcmd.name} -- #{subcmd.short_help}\n" + end + else + args = @match[1].split(/[ \t]+/) + subcmd = args.shift + subcmd.downcase! + if subcmd =~ /^no/i + set_on = false + subcmd = subcmd[2..-1] + else + set_on = true + end + for try_subcmd in Subcommands do + if (subcmd.size >= try_subcmd.min) and + (try_subcmd.name[0..subcmd.size-1] == subcmd) + begin + if try_subcmd.is_bool + if args.size > 0 + set_on = get_onoff(args[0]) + end + end + case try_subcmd.name + when /^annotate$/ + level = get_int(args[0], "Set annotate", 0, 3, 0) + if level + Debugger.annotate = level + else + return + end + if defined?(Debugger::RDEBUG_SCRIPT) + # rdebug was called initially. 1st arg is script name. + Command.settings[:argv][1..-1] = args + else + # rdebug wasn't called initially. 1st arg is not script name. + Command.settings[:argv] = args + end + when /^args$/ + Command.settings[:argv][1..-1] = args + when /^autolist$/ + Command.settings[:autolist] = (set_on ? 1 : 0) + when /^autoeval$/ + Command.settings[:autoeval] = set_on + when /^basename$/ + Command.settings[:basename] = set_on + when /^callstyle$/ + if args[0] + arg = args[0].downcase.to_sym + case arg + when :short, :last, :tracked + Command.settings[:callstyle] = arg + Debugger.track_frame_args = arg == :tracked ? true : false + print "%s\n" % show_setting(try_subcmd.name) + return + end + end + print "Invalid call style #{arg}. Should be one of: " + + "'short', 'last', or 'tracked'.\n" + when /^trace$/ + Command.settings[:stack_trace_on_error] = set_on + when /^fullpath$/ + Command.settings[:full_path] = set_on + when /^autoreload$/ + Command.settings[:reload_source_on_change] = set_on + when /^autoirb$/ + Command.settings[:autoirb] = (set_on ? 1 : 0) + when /^debuggertesting$/ + Command.settings[:debuggertesting] = set_on + if set_on + Command.settings[:basename] = true + end + when /^forcestep$/ + self.class.settings[:force_stepping] = set_on + when /^history$/ + if 2 == args.size + interface = @state.interface + case args[0] + when /^save$/ + interface.history_save = get_onoff(args[1]) + when /^size$/ + interface.history_length = get_int(args[1], + "Set history size") + else + print "Invalid history parameter #{args[0]}. Should be 'save' or 'size'.\n" + end + else + print "Need two parameters for 'set history'; got #{args.size}.\n" + return + end + when /^keep-frame-bindings$/ + Debugger.keep_frame_binding = set_on + when /^linetrace\+$/ + self.class.settings[:tracing_plus] = set_on + when /^linetrace$/ + Debugger.tracing = set_on + when /^listsize$/ + listsize = get_int(args[0], "Set listsize", 1, nil, 10) + if listsize + self.class.settings[:listsize] = listsize + else + return + end +# when /^post-mortem$/ +# unless Debugger.post_mortem? == set_on +# if set_on +# Debugger.post_mortem +# else +# errmsg "Can't turn off post-mortem once it is on.\n" +# return +# end +# end + when /^width$/ + width = get_int(args[0], "Set width", 10, nil, 80) + if width + self.class.settings[:width] = width + ENV['COLUMNS'] = width.to_s + else + return + end + else + print "Unknown setting #{@match[1]}.\n" + return + end + print "%s\n" % show_setting(try_subcmd.name) + return + rescue RuntimeError + return + end + end + end + print "Unknown set command #{subcmd}\n" + end + end + + class << self + def help_command + "set" + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + str += "\n" + subcmd.long_help if subcmd.long_help + return str + else + return "Invalid 'set' subcommand '#{args[1]}'." + end + end + s = %{ + Modifies parts of the ruby-debug environment. Boolean values take + on, off, 1 or 0. + You can see these environment settings with the \"show\" command. + + -- + List of set subcommands: + -- + } + for subcmd in Subcommands do + s += "set #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end +end diff --git a/cli/ruby-debug/commands/show.rb b/cli/ruby-debug/commands/show.rb new file mode 100644 index 0000000..f2992ad --- /dev/null +++ b/cli/ruby-debug/commands/show.rb @@ -0,0 +1,253 @@ +module Debugger + # Mix-in module to showing settings + module ShowFunctions # :nodoc: + def show_setting(setting_name) + case setting_name + when /^annotate$/ + Debugger.annotate ||= 0 + return ("Annotation level is #{Debugger.annotate}") + when /^args$/ + if Command.settings[:argv] and Command.settings[:argv].size > 0 + if defined?(Debugger::RDEBUG_SCRIPT) + # rdebug was called initially. 1st arg is script name. + args = Command.settings[:argv][1..-1].join(' ') + else + # rdebug wasn't called initially. 1st arg is not script name. + args = Command.settings[:argv].join(' ') + end + else + args = '' + end + return "Argument list to give program being debugged when it is started is \"#{args}\"." + when /^autolist$/ + on_off = Command.settings[:autolist] > 0 + return "autolist is #{show_onoff(on_off)}." + when /^autoeval$/ + on_off = Command.settings[:autoeval] + return "autoeval is #{show_onoff(on_off)}." + when /^autoreload$/ + on_off = Command.settings[:reload_source_on_change] + return "autoreload is #{show_onoff(on_off)}." + when /^autoirb$/ + on_off = Command.settings[:autoirb] > 0 + return "autoirb is #{show_onoff(on_off)}." + when /^basename$/ + on_off = Command.settings[:basename] + return "basename is #{show_onoff(on_off)}." + when /^callstyle$/ + style = Command.settings[:callstyle] + return "Frame call-display style is #{style}." + when /^commands(:?\s+(\d+))?$/ + if @state.interface.readline_support? + s = ''; + args = @match[1].split + if args[1] + first_line = args[1].to_i - 4 + last_line = first_line + 10 - 1 + if first_line > Readline::HISTORY.length + first_line = last_line = Readline::HISTORY.length + elsif first_line <= 0 + first_line = 1 + end + if last_line > Readline::HISTORY.length + last_line = Readline::HISTORY.length + end + i = first_line + commands = Readline::HISTORY.to_a[first_line..last_line] + else + if Readline::HISTORY.length > 10 + commands = Readline::HISTORY.to_a[-10..-1] + i = Readline::HISTORY.length - 10 + else + commands = Readline::HISTORY.to_a + i = 1 + end + end + commands.each do |cmd| + s += ("%5d %s\n" % [i, cmd]) + i += 1 + end + else + s='No readline suport' + end + return s + when /^debuggertesting$/ + on_off = Command.settings[:debuggertesting] + return "Currently testing the debugger is #{show_onoff(on_off)}." + when /^forcestep$/ + on_off = self.class.settings[:force_stepping] + return "force-stepping is #{show_onoff(on_off)}." + when /^fullpath$/ + on_off = Command.settings[:full_path] + return "Displaying frame's full file names is #{show_onoff(on_off)}." + when /^history(:?\s+(filename|save|size))?$/ + args = @match[1].split + interface = @state.interface + if args[1] + show_save = show_size = show_filename = false + prefix = false + if args[1] == "save" + show_save = true + elsif args[1] == "size" + show_size = true + elsif args[1] == "filename" + show_filename = true + end + else + show_save = show_size = show_filename = true + prefix = true + end + s = [] + if show_filename + msg = (prefix ? "filename: " : "") + + "The filename in which to record the command history is " + + "#{interface.histfile.inspect}" + s << msg + end + if show_save + msg = (prefix ? "save: " : "") + + "Saving of history save is #{show_onoff(interface.history_save)}." + s << msg + end + if show_size + msg = (prefix ? "size: " : "") + + "Debugger history size is #{interface.history_length}" + s << msg + end + return s.join("\n") + when /^keep-frame-bindings$/ + on_off = Debugger.keep_frame_binding? + return "keep-frame-bindings is #{show_onoff(on_off)}." + when /^linetrace$/ + on_off = Debugger.tracing + return "line tracing is #{show_onoff(on_off)}." + when /^linetrace\+$/ + on_off = Command.settings[:tracing_plus] + if on_off + return "line tracing style is different consecutive lines." + else + return "line tracing style is every line." + end + when /^listsize$/ + listlines = Command.settings[:listsize] + return "Number of source lines to list by default is #{listlines}." + when /^port$/ + return "server port is #{Debugger::PORT}." + when /^post-mortem$/ + on_off = Debugger.post_mortem? + return "post-mortem handling is #{show_onoff(on_off)}." + when /^trace$/ + on_off = Command.settings[:stack_trace_on_error] + return "Displaying stack trace is #{show_onoff(on_off)}." + when /^version$/ + return "ruby-debug #{Debugger::VERSION}" + when /^width$/ + return "width is #{self.class.settings[:width]}." + else + return "Unknown show subcommand #{setting_name}." + end + end + end + + # Implements debugger "show" command. + class ShowCommand < Command + + Subcommands = + [ + ['annotate', 2, "Show annotation level", +"0 == normal; 2 == output annotated suitably for use by programs that control +ruby-debug."], + ['args', 2, + "Show argument list to give program being debugged when it is started", +"Follow this command with any number of args, to be passed to the program."], + ['autoeval', 4, "Show if unrecognized command are evaluated"], + ['autolist', 4, "Show if 'list' commands is run on breakpoints"], + ['autoirb', 4, "Show if IRB is invoked on debugger stops"], + ['autoreload', 4, "Show if source code is reloaded when changed"], + ['basename', 1, "Show if basename used in reporting files"], + ['callstyle', 2, "Show paramater style used showing call frames"], + ['commands', 2, "Show the history of commands you typed", +"You can supply a command number to start with."], + ['forcestep', 1, "Show if sure 'next/step' forces move to a new line"], + ['fullpath', 2, "Show if full file names are displayed in frames"], + ['history', 2, "Generic command for showing command history parameters", +"show history filename -- Show the filename in which to record the command history +show history save -- Show saving of the history record on exit +show history size -- Show the size of the command history"], + ['keep-frame-bindings', 1, "Save frame binding on each call"], + ['linetrace', 3, "Show line execution tracing"], + ['linetrace+', 10, + "Show if consecutive lines should be different are shown in tracing"], + ['listsize', 3, "Show number of source lines to list by default"], + ['port', 3, "Show server port"], + ['post-mortem', 3, "Show whether we go into post-mortem debugging on an uncaught exception"], + ['trace', 1, + "Show if a stack trace is displayed when 'eval' raises exception"], + ['version', 1, + "Show what version of the debugger this is"], + ['width', 1, + "Show the number of characters the debugger thinks are in a line"], + ].map do |name, min, short_help, long_help| + SubcmdStruct.new(name, min, short_help, long_help) + end unless defined?(Subcommands) + + self.allow_in_control = true + + def regexp + /^show (?: \s+ (.+) )?$/xi + end + + def execute + if not @match[1] + print "\"show\" must be followed by the name of an show command:\n" + print "List of show subcommands:\n\n" + for subcmd in Subcommands do + print "show #{subcmd.name} -- #{subcmd.short_help}\n" + end + else + args = @match[1].split(/[ \t]+/) + param = args.shift + subcmd = find(Subcommands, param) + if subcmd + print "%s\n" % show_setting(subcmd.name) + else + print "Unknown show command #{param}\n" + end + end + end + + class << self + def help_command + "show" + end + + def help(args) + if args[1] + s = args[1] + subcmd = Subcommands.find do |try_subcmd| + (s.size >= try_subcmd.min) and + (try_subcmd.name[0..s.size-1] == s) + end + if subcmd + str = subcmd.short_help + '.' + str += "\n" + subcmd.long_help if subcmd.long_help + return str + else + return "Invalid 'show' subcommand '#{args[1]}'." + end + end + s = " + Generic command for showing things about the debugger. + + -- + List of show subcommands: + -- + " + for subcmd in Subcommands do + s += "show #{subcmd.name} -- #{subcmd.short_help}\n" + end + return s + end + end + end +end diff --git a/cli/ruby-debug/commands/source.rb b/cli/ruby-debug/commands/source.rb new file mode 100644 index 0000000..a5e7179 --- /dev/null +++ b/cli/ruby-debug/commands/source.rb @@ -0,0 +1,36 @@ +module Debugger + # Implements debugger "source" command. + class SourceCommand < Command + self.allow_in_control = true + + def regexp + /^\s* so(?:urce)? \s+ (.+) $/x + end + + def execute + file = File.expand_path(@match[1]).strip + unless File.exist?(file) + errmsg "Command file '#{file}' is not found\n" + return + end + if @state and @state.interface + @state.interface.command_queue += File.open(file).readlines + else + Debugger.run_script(file, @state) + end + end + + class << self + def help_command + 'source' + end + + def help(cmd) + %{ + source FILE\texecutes a file containing debugger commands + } + end + end + end + +end diff --git a/cli/ruby-debug/commands/stepping.rb b/cli/ruby-debug/commands/stepping.rb new file mode 100644 index 0000000..5b1c3b2 --- /dev/null +++ b/cli/ruby-debug/commands/stepping.rb @@ -0,0 +1,81 @@ +module Debugger + # Mix-in module to assist in command parsing. + module SteppingFunctions # :nodoc: + def parse_stepping_args(command_name, match) + if match[1].nil? + force = Command.settings[:force_stepping] + elsif match[1] == '+' + force = true + elsif match[1] == '-' + force = false + end + steps = get_int(match[2], command_name, 1) + return [steps, force] + end + end + # Implements debugger "next" command. + class NextCommand < Command + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s* n(?:ext)? + ([+-])?(?:\s+(\S+))? + \s*$/x + end + + def execute + steps, force = parse_stepping_args("Next", @match) + return unless steps + @state.context.step_over steps, @state.frame_pos, force + @state.proceed + end + + class << self + def help_command + 'next' + end + + def help(cmd) + %{ + n[ext][+-]?[ nnn]\tstep over once or nnn times, + \t\t'+' forces to move to another line. + \t\t'-' is the opposite of '+' and disables the force_stepping setting. + } + end + end + end + + # Implements debugger "step" command. + class StepCommand < Command + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s* s(?:tep)? + ([+-])?(?:\s+(\S+))? + \s*$/x + end + + def execute + steps, force = parse_stepping_args("Step", @match) + return unless steps + @state.context.step(steps, force) + @state.proceed + end + + class << self + def help_command + 'step' + end + + def help(cmd) + %{ + s[tep][+-]?[ nnn]\tstep (into methods) once or nnn times + \t\t'+' forces to move to another line. + \t\t'-' is the opposite of '+' and disables the force_stepping setting. + } + end + end + end +end diff --git a/cli/ruby-debug/commands/threads.rb b/cli/ruby-debug/commands/threads.rb new file mode 100644 index 0000000..c06c8bf --- /dev/null +++ b/cli/ruby-debug/commands/threads.rb @@ -0,0 +1,189 @@ +module Debugger + module ThreadFunctions # :nodoc: + def display_context(c, show_top_frame=true) + c_flag = c.thread == Thread.current ? '+' : ' ' + c_flag = '$' if c.suspended? + d_flag = c.ignored? ? '!' : ' ' + print "%s%s", c_flag, d_flag + print "%d ", c.thnum + print "%s\t", c.thread.inspect + if c.stack_size > 0 and show_top_frame + print "%s:%d", c.frame_file(0), c.frame_line(0) + end + print "\n" + end + + def parse_thread_num(subcmd, arg) + if '' == arg + errmsg "'%s' needs a thread number\n" % subcmd + nil + else + thread_num = get_int(arg, "thread #{subcmd}", 1) + return nil unless thread_num + get_context(thread_num) + end + end + + def parse_thread_num_for_cmd(subcmd, arg) + c = parse_thread_num(subcmd, arg) + return nil unless c + case + when nil == c + errmsg "No such thread.\n" + when @state.context == c + errmsg "It's the current thread.\n" + when c.ignored? + errmsg "Can't #{subcmd} to the debugger thread #{arg}.\n" + else # Everything is okay + return c + end + return nil + end + end + + class ThreadListCommand < Command # :nodoc: + self.allow_in_control = true + + def regexp + /^\s*th(?:read)?\s+l(?:ist)?\s*$/ + end + + def execute + threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c| + display_context(c) + end + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] l[ist]\t\t\tlist all threads + } + end + end + end + + class ThreadStopCommand < Command # :nodoc: + self.allow_in_control = true + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s*th(?:read)?\s+stop\s*(\S*)\s*$/ + end + + def execute + c = parse_thread_num_for_cmd("thread stop", @match[1]) + return unless c + c.suspend + display_context(c) + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] stop \t\tstop thread nnn + } + end + end + end + + class ThreadResumeCommand < Command # :nodoc: + self.allow_in_post_mortem = false + self.allow_in_control = true + self.need_context = true + + def regexp + /^\s*th(?:read)?\s+resume\s*(\S*)\s*$/ + end + + def execute + c = parse_thread_num_for_cmd("thread resume", @match[1]) + return unless c + if !c.thread.stop? + print "Already running." + return + end + c.resume + display_context(c) + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] resume \t\tresume thread nnn + } + end + end + end + + # Thread switch Must come after "Thread resume" because "switch" is + # optional + + class ThreadSwitchCommand < Command # :nodoc: + self.allow_in_control = true + self.allow_in_post_mortem = false + self.need_context = true + + def regexp + /^\s*th(?:read)?\s*(?:sw(?:itch)?)?\s+(\S+)\s*$/ + end + + def execute + c = parse_thread_num_for_cmd("thread switch", @match[1]) + return unless c + display_context(c) + c.stop_next = 1 + c.thread.run + @state.proceed + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] [sw[itch]] \tswitch thread context to nnn + } + end + end + end + + class ThreadCurrentCommand < Command # :nodoc: + self.need_context = true + + def regexp + /^\s*th(?:read)?\s*(?:cur(?:rent)?)?\s*$/ + end + + def execute + display_context(@state.context) + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] [cur[rent]]\t\tshow current thread + } + end + end + end +end diff --git a/cli/ruby-debug/commands/tmate.rb b/cli/ruby-debug/commands/tmate.rb new file mode 100644 index 0000000..060a7d1 --- /dev/null +++ b/cli/ruby-debug/commands/tmate.rb @@ -0,0 +1,36 @@ +module Debugger + if RUBY_PLATFORM =~ /darwin/ + class TextMateCommand < Command # :nodoc: + def regexp + /^\s*tm(?:ate)?(?:\s*(\d+))?$/ + end + + def execute + if @match[1] + frm_n = @match[1].to_i + if frm_n > @state.context.stack_size || frm_n == 0 + print "Wrong frame number\n" + return + end + file, line = @state.context.frame_file(frm_n-1), @state.context.frame_line(frm_n-1) + else + file, line = @state.file, @state.line + end + %x|open 'txmt://open?url=file://#{File.expand_path(file)}&line=#{line}'| + end + + class << self + def help_command + 'tmate' + end + + def help(cmd) + %{ + tm[ate] n\topens a current file in TextMate. + \t\tIt uses n-th frame if arg (n) is specifed. + } + end + end + end + end +end diff --git a/cli/ruby-debug/commands/trace.rb b/cli/ruby-debug/commands/trace.rb new file mode 100644 index 0000000..ed063aa --- /dev/null +++ b/cli/ruby-debug/commands/trace.rb @@ -0,0 +1,57 @@ +module Debugger + class TraceCommand < Command # :nodoc: + def regexp + /^\s* tr(?:ace)? (?: \s+ (\S+)) # on |off | var(iable) + (?: \s+ (\S+))? # (all | variable-name)? + (?: \s+ (\S+))? \s* # (stop | nostop)? + $/ix + end + + def execute + if @match[1] =~ /on|off/ + onoff = 'on' == @match[1] + if @match[2] + Debugger.current_context.tracing = onoff + print "Tracing %s all threads.\n" % (onoff ? 'on' : 'off') + else + Debugger.tracing = onoff + print "Tracing %s on current thread.\n" % (onoff ? 'on' : 'off') + end + elsif @match[1] =~ /var(?:iable)?/ + varname=@match[2] + if debug_eval("defined?(#{varname})") + if @match[3] && @match[3] !~ /(:?no)?stop/ + errmsg("expecting 'stop' or 'nostop'; got %s\n" % @match[3]) + else + dbg_cmd = if @match[3] && (@match[3] !~ /nostop/) + 'debugger' else '' end + end + eval(" + trace_var(:#{varname}) do |val| + print \"traced variable #{varname} has value \#{val}\n\" + #{dbg_cmd} + end") + else + errmsg "#{varname} is not a global variable.\n" + end + else + errmsg("expecting 'on', 'off', 'var' or 'variable'; got: %s\n" % + @match[1]) + end + end + + class << self + def help_command + 'trace' + end + + def help(cmd) + %{ + tr[ace] (on|off)\tset trace mode of current thread + tr[ace] (on|off) all\tset trace mode of all threads + tr[ace] var(iable) VARNAME [stop|nostop]\tset trace variable on VARNAME + } + end + end + end +end diff --git a/cli/ruby-debug/commands/variables.rb b/cli/ruby-debug/commands/variables.rb new file mode 100644 index 0000000..e326e46 --- /dev/null +++ b/cli/ruby-debug/commands/variables.rb @@ -0,0 +1,199 @@ +module Debugger + module VarFunctions # :nodoc: + def var_list(ary, b = get_binding) + ary.sort! + for v in ary + begin + s = debug_eval(v, b).inspect + rescue + begin + s = debug_eval(v, b).to_s + rescue + s = "*Error in evaluation*" + end + end + if s.size > self.class.settings[:width] + s[self.class.settings[:width]-3 .. -1] = "..." + end + print "%s = %s\n", v, s + end + end + def var_class_self + obj = debug_eval('self') + var_list(obj.class.class_variables, get_binding) + end + end + + # Implements the debugger 'var class' command. + class VarClassVarCommand < Command + def regexp + /^\s*v(?:ar)?\s+cl(?:ass)?/ + end + + def execute + unless @state.context + errmsg "can't get class variables here.\n" + return + end + var_class_self + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] cl[ass] \t\t\tshow class variables of self + } + end + end + end + + class VarConstantCommand < Command # :nodoc: + def regexp + /^\s*v(?:ar)?\s+co(?:nst(?:ant)?)?\s+/ + end + + def execute + obj = debug_eval(@match.post_match) + if obj.kind_of? Module + constants = debug_eval("#{@match.post_match}.constants") + constants.sort! + for c in constants + next if c =~ /SCRIPT/ + value = obj.const_get(c) rescue "ERROR: #{$!}" + print " %s => %p\n", c, value + end + else + print "Should be Class/Module: %s\n", @match.post_match + end + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] c[onst] \t\tshow constants of object + } + end + end + end + + class VarGlobalCommand < Command # :nodoc: + def regexp + /^\s*v(?:ar)?\s+g(?:lobal)?\s*$/ + end + + def execute + var_list(global_variables) + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] g[lobal]\t\t\tshow global variables + } + end + end + end + + class VarInstanceCommand < Command # :nodoc: + def regexp + /^\s*v(?:ar)?\s+ins(?:tance)?\s*/ + end + + def execute + obj = debug_eval(@match.post_match.empty? ? 'self' : @match.post_match) + var_list(obj.instance_variables, obj.instance_eval{binding()}) + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] i[nstance] \tshow instance variables of object + } + end + end + end + + # Implements the debugger 'var local' command. + class VarLocalCommand < Command + def regexp + /^\s*v(?:ar)?\s+l(?:ocal)?\s*$/ + end + + def execute + locals = @state.context.frame_locals(@state.frame_pos) + _self = @state.context.frame_self(@state.frame_pos) + locals.keys.sort.each do |name| + print " %s => %p\n", name, locals[name] + end + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] l[ocal]\t\t\tshow local variables + } + end + end + end + + # Implements the debugger 'var inherit' command. + begin + require 'classtree' + have_classtree = true + rescue LoadError + have_classtree = false + end + + class VarInheritCommand < Command + def regexp + /^\s*v(?:ar)?\s+ct\s*/ + end + + def execute + unless @state.context + errmsg "can't get object inheritance.\n" + return + end + puts @match.post_match + obj = debug_eval("#{@match.post_match}.classtree") + if obj + print obj + else + errmsg "Trouble getting object #{@match.post_match}\n" + end + end + + class << self + def help_command + 'var' + end + + def help(cmd) + %{ + v[ar] ct\t\t\tshow class heirarchy of object + } + end + end + end if have_classtree + +end diff --git a/cli/ruby-debug/debugger.rb b/cli/ruby-debug/debugger.rb new file mode 100644 index 0000000..d581c05 --- /dev/null +++ b/cli/ruby-debug/debugger.rb @@ -0,0 +1,5 @@ +# Module/Package to do the most-common thing: get into the debugger with +# minimal fuss. Compare with: require "debug" +require "ruby-debug" +Debugger.start +debugger \ No newline at end of file diff --git a/cli/ruby-debug/helper.rb b/cli/ruby-debug/helper.rb new file mode 100644 index 0000000..f159c3c --- /dev/null +++ b/cli/ruby-debug/helper.rb @@ -0,0 +1,69 @@ +module Debugger + + module ParseFunctions + Position_regexp = '(?:(\d+)|(.+?)[:.#]([^.:\s]+))' + + # Parse 'str' of command 'cmd' as an integer between + # min and max. If either min or max is nil, that + # value has no bound. + def get_int(str, cmd, min=nil, max=nil, default=1) + return default unless str + begin + int = Integer(str) + if min and int < min + print "%s argument '%s' needs to at least %s.\n" % [cmd, str, min] + return nil + elsif max and int > max + print "%s argument '%s' needs to at most %s.\n" % [cmd, str, max] + return nil + end + return int + rescue + print "%s argument '%s' needs to be a number.\n" % [cmd, str] + return nil + end + end + + # Return true if arg is 'on' or 1 and false arg is 'off' or 0. + # Any other value raises RuntimeError. + def get_onoff(arg, default=nil, print_error=true) + if arg.nil? or arg == '' + if default.nil? + if print_error + print "Expecting 'on', 1, 'off', or 0. Got nothing.\n" + raise RuntimeError + end + return default + end + end + case arg.downcase + when '1', 'on' + return true + when '0', 'off' + return false + else + if print_error + print "Expecting 'on', 1, 'off', or 0. Got: %s.\n" % arg.to_s + raise RuntimeError + end + end + end + + # Return 'on' or 'off' for supplied parameter. The parmeter should + # be true, false or nil. + def show_onoff(bool) + if not [TrueClass, FalseClass, NilClass].member?(bool.class) + return "??" + end + return bool ? 'on' : 'off' + end + + # Return true if code is syntactically correct for Ruby. + def syntax_valid?(code) + eval("BEGIN {return true}\n#{code}", nil, "", 0) + rescue Exception + false + end + + end +end diff --git a/cli/ruby-debug/interface.rb b/cli/ruby-debug/interface.rb new file mode 100644 index 0000000..63feea1 --- /dev/null +++ b/cli/ruby-debug/interface.rb @@ -0,0 +1,232 @@ +module Debugger + class Interface # :nodoc: + attr_writer :have_readline # true if Readline is available + + def initialize + @have_readline = false + end + + # Common routine for reporting debugger error messages. + # Derived classed may want to override this to capture output. + def errmsg(*args) + if Debugger.annotate.to_i > 2 + aprint 'error-begin' + print(*args) + aprint '' + else + print '*** ' + print(*args) + end + end + + # Format msg with gdb-style annotation header + def afmt(msg, newline="\n") + "\032\032#{msg}#{newline}" + end + + def aprint(msg) + print afmt(msg) + end + + end + + class LocalInterface < Interface # :nodoc: + attr_accessor :command_queue + attr_accessor :histfile + attr_accessor :history_save + attr_accessor :history_length + attr_accessor :restart_file + + unless defined?(FILE_HISTORY) + FILE_HISTORY = ".rdebug_hist" + end + def initialize() + super + @command_queue = [] + @have_readline = false + @history_save = true + # take gdb's default + @history_length = ENV["HISTSIZE"] ? ENV["HISTSIZE"].to_i : 256 + @histfile = File.join(ENV["HOME"]||ENV["HOMEPATH"]||".", + FILE_HISTORY) + open(@histfile, 'r') do |file| + file.each do |line| + line.chomp! + Readline::HISTORY << line + end + end if File.exist?(@histfile) + @restart_file = nil + end + + def read_command(prompt) + readline(prompt, true) + end + + def confirm(prompt) + readline(prompt, false) + end + + def print(*args) + STDOUT.printf(*args) + end + + def close + end + + # Things to do before quitting + def finalize + if Debugger.method_defined?("annotate") and Debugger.annotate.to_i > 2 + print "\032\032exited\n\n" + end + if Debugger.respond_to?(:save_history) + Debugger.save_history + end + end + + def readline_support? + @have_readline + end + + private + begin + require 'readline' + class << Debugger + @have_readline = true + define_method(:save_history) do + iface = self.handler.interface + iface.histfile ||= File.join(ENV["HOME"]||ENV["HOMEPATH"]||".", + FILE_HISTORY) + open(iface.histfile, 'w') do |file| + Readline::HISTORY.to_a.last(iface.history_length).each do |line| + file.puts line unless line.strip.empty? + end if defined?(iface.history_save) and iface.history_save + end rescue nil + end + public :save_history + end + Debugger.debug_at_exit do + finalize if respond_to?(:finalize) + end + + def readline(prompt, hist) + Readline::readline(prompt, hist) + end + rescue LoadError + def readline(prompt, hist) + @histfile = '' + @hist_save = false + STDOUT.print prompt + STDOUT.flush + line = STDIN.gets + exit unless line + line.chomp! + line + end + end + end + + class RemoteInterface < Interface # :nodoc: + attr_accessor :command_queue + attr_accessor :histfile + attr_accessor :history_save + attr_accessor :history_length + attr_accessor :restart_file + + def initialize(socket) + @command_queue = [] + @socket = socket + @history_save = false + @history_length = 256 + @histfile = '' + # Do we read the histfile? +# open(@histfile, 'r') do |file| +# file.each do |line| +# line.chomp! +# Readline::HISTORY << line +# end +# end if File.exist?(@histfile) + @restart_file = nil + end + + def close + @socket.close + rescue Exception + end + + def confirm(prompt) + send_command "CONFIRM #{prompt}" + end + + def finalize + end + + def read_command(prompt) + send_command "PROMPT #{prompt}" + end + + def readline_support? + false + end + + def print(*args) + @socket.printf(*args) + end + + private + + def send_command(msg) + @socket.puts msg + result = @socket.gets + raise IOError unless result + result.chomp + end + end + + class ScriptInterface < Interface # :nodoc: + attr_accessor :command_queue + attr_accessor :histfile + attr_accessor :history_save + attr_accessor :history_length + attr_accessor :restart_file + def initialize(file, out, verbose=false) + super() + @command_queue = [] + @file = file.respond_to?(:gets) ? file : open(file) + @out = out + @verbose = verbose + @history_save = false + @history_length = 256 # take gdb default + @histfile = '' + end + + def finalize + end + + def read_command(prompt) + while result = @file.gets + puts "# #{result}" if @verbose + next if result =~ /^\s*#/ + next if result.strip.empty? + break + end + raise IOError unless result + result.chomp! + end + + def readline_support? + false + end + + def confirm(prompt) + 'y' + end + + def print(*args) + @out.printf(*args) + end + + def close + @file.close + end + end +end diff --git a/cli/ruby-debug/processor.rb b/cli/ruby-debug/processor.rb new file mode 100644 index 0000000..dbb85a2 --- /dev/null +++ b/cli/ruby-debug/processor.rb @@ -0,0 +1,474 @@ +require 'ruby-debug/interface' +require 'ruby-debug/command' + +module Debugger + + # Should this be a mixin? + class Processor # :nodoc + attr_accessor :interface + + # Format msg with gdb-style annotation header + def afmt(msg, newline="\n") + "\032\032#{msg}#{newline}" + end + + def aprint(msg) + print afmt(msg) if Debugger.annotate.to_i > 2 + end + + # FIXME: use delegate? + def errmsg(*args) + @interface.errmsg(*args) + end + + # Callers of this routine should make sure to use comma to + # separate format argments rather than %. Otherwise it seems that + # if the string you want to print has format specifier, which + # could happen if you are trying to show say a source-code line + # with "puts" or "print" in it, this print routine will give an + # error saying it is looking for more arguments. + def print(*args) + @interface.print(*args) + end + + end + + class CommandProcessor < Processor # :nodoc: + attr_reader :display + + # FIXME: get from Command regexp method. + @@Show_breakpoints_postcmd = [ + /^\s*b(?:reak)?/, + /^\s* cond(?:ition)? (?:\s+(\d+)\s*(.*))?$/ix, + /^\s*del(?:ete)?(?:\s+(.*))?$/ix, + /^\s* dis(?:able)? (?:\s+(.*))?$/ix, + /^\s* en(?:able)? (?:\s+(.*))?$/ix, + # "tbreak", "clear", + ] + @@Show_annotations_run = [ + /^\s*c(?:ont(?:inue)?)?(?:\s+(.*))?$/, + /^\s*fin(?:ish)?$/, + /^\s*n(?:ext)?([+-])?(?:\s+(.*))?$/, + /^\s*s(?:tep)?([+-])?(?:\s+(.*))?$/ + ] + + @@Show_annotations_postcmd = [ + /^\s* down (?:\s+(.*))? .*$/x, + /^\s* f(?:rame)? (?:\s+ (.*))? \s*$/x, + /^\s* u(?:p)? (?:\s+(.*))?$/x + ] + + def initialize(interface = LocalInterface.new) + @interface = interface + @display = [] + + @mutex = Mutex.new + @last_cmd = nil + @last_file = nil # Filename the last time we stopped + @last_line = nil # line number the last time we stopped + @debugger_breakpoints_were_empty = false # Show breakpoints 1st time + @debugger_displays_were_empty = true # No display 1st time + @debugger_context_was_dead = true # Assume we haven't started. + end + + def interface=(interface) + @mutex.synchronize do + @interface.close if @interface + @interface = interface + end + end + + require 'pathname' # For cleanpath + + # Regularize file name. + # This is also used as a common funnel place if basename is + # desired or if we are working remotely and want to change the + # basename. Or we are eliding filenames. + def self.canonic_file(filename) + # For now we want resolved filenames + if Command.settings[:basename] + File.basename(filename) + else + # Cache this? + Pathname.new(filename).cleanpath.to_s + end + end + + def self.print_location_and_text(file, line) + file_line = "%s:%s\n%s" % [canonic_file(file), line, + Debugger.line_at(file, line)] + # FIXME: use annotations routines + if Debugger.annotate.to_i > 2 + file_line = "\032\032source #{file_line}" + elsif ENV['EMACS'] + file_line = "\032\032#{file_line}" + end + print file_line + end + + def self.protect(mname) + alias_method "__#{mname}", mname + module_eval %{ + def #{mname}(*args) + @mutex.synchronize do + return unless @interface + __#{mname}(*args) + end + rescue IOError, Errno::EPIPE + self.interface = nil + rescue SignalException + raise + rescue Exception + print "INTERNAL ERROR!!! #\{$!\}\n" rescue nil + print $!.backtrace.map{|l| "\t#\{l\}"}.join("\n") rescue nil + end + } + end + + def at_breakpoint(context, breakpoint) + aprint 'stopped' if Debugger.annotate.to_i > 2 + n = Debugger.breakpoints.index(breakpoint) + 1 + file = CommandProcessor.canonic_file(breakpoint.source) + line = breakpoint.pos + if Debugger.annotate.to_i > 2 + print afmt("source #{file}:#{line}") + end + print "Breakpoint %d at %s:%s\n", n, file, line + end + protect :at_breakpoint + + def at_catchpoint(context, excpt) + aprint 'stopped' if Debugger.annotate.to_i > 2 + file = CommandProcessor.canonic_file(context.frame_file(0)) + line = context.frame_line(0) + print afmt("%s:%d" % [file, line]) if ENV['EMACS'] + print "Catchpoint at %s:%d: `%s' (%s)\n", file, line, excpt, excpt.class + fs = context.stack_size + tb = caller(0)[-fs..-1] + if tb + for i in tb + print "\tfrom %s\n", i + end + end + end + protect :at_catchpoint + + def at_tracing(context, file, line) + return if defined?(Debugger::RDEBUG_FILE) && + Debugger::RDEBUG_FILE == file # Don't trace ourself + @last_file = CommandProcessor.canonic_file(file) + file = CommandProcessor.canonic_file(file) + unless file == @last_file and @last_line == line and + Command.settings[:tracing_plus] + print "Tracing(%d):%s:%s %s", + context.thnum, file, line, Debugger.line_at(file, line) + @last_file = file + @last_line = line + end + always_run(context, file, line, 2) + end + protect :at_tracing + + def at_line(context, file, line) + process_commands(context, file, line) + end + protect :at_line + + def at_return(context, file, line) + context.stop_frame = -1 + process_commands(context, file, line) + end + + private + + # The prompt shown before reading a command. + def prompt(context) + p = '(rdb:%s) ' % (context.dead? ? 'post-mortem' : context.thnum) + p = afmt("pre-prompt")+p+"\n"+afmt("prompt") if + Debugger.annotate.to_i > 2 + return p + end + + # Run these commands, for example display commands or possibly + # the list or irb in an "autolist" or "autoirb". + # We return a list of commands that are acceptable to run bound + # to the current state. + def always_run(context, file, line, run_level) + event_cmds = Command.commands.select{|cmd| cmd.event } + + # Remove some commands in post-mortem + event_cmds = event_cmds.find_all do |cmd| + cmd.allow_in_post_mortem + end if context.dead? + + state = State.new do |s| + s.context = context + s.file = file + s.line = line + s.binding = context.frame_binding(0) + s.display = display + s.interface = interface + s.commands = event_cmds + end + @interface.state = state if @interface.respond_to?('state=') + + # Bind commands to the current state. + commands = event_cmds.map{|cmd| cmd.new(state)} + + commands.select do |cmd| + cmd.class.always_run >= run_level + end.each {|cmd| cmd.execute} + return state, commands + end + + # Handle debugger commands + def process_commands(context, file, line) + state, commands = always_run(context, file, line, 1) + $rdebug_state = state if Command.settings[:debuggertesting] + splitter = lambda do |str| + str.split(/;/).inject([]) do |m, v| + if m.empty? + m << v + else + if m.last[-1] == ?\\ + m.last[-1,1] = '' + m.last << ';' << v + else + m << v + end + end + m + end + end + + preloop(commands, context) + CommandProcessor.print_location_and_text(file, line) + while !state.proceed? + input = if @interface.command_queue.empty? + @interface.read_command(prompt(context)) + else + @interface.command_queue.shift + end + break unless input + catch(:debug_error) do + if input == "" + next unless @last_cmd + input = @last_cmd + else + @last_cmd = input + end + splitter[input].each do |cmd| + one_cmd(commands, context, cmd) + postcmd(commands, context, cmd) + end + end + end + postloop(commands, context) + end # process_commands + + def one_cmd(commands, context, input) + if cmd = commands.find{ |c| c.match(input) } + if context.dead? && cmd.class.need_context + p cmd + print "Command is unavailable\n" + else + cmd.execute + end + else + unknown_cmd = commands.find{|cmd| cmd.class.unknown } + if unknown_cmd + unknown_cmd.execute + else + errmsg "Unknown command: \"#{input}\". Try \"help\".\n" + end + end + end + + def preloop(commands, context) + aprint('stopped') if Debugger.annotate.to_i > 2 + if context.dead? + unless @debugger_context_was_dead + if Debugger.annotate.to_i > 2 + aprint('exited') + print "The program finished.\n" + end + @debugger_context_was_dead = true + end + end + + if Debugger.annotate.to_i > 2 + # if we are here, the stack frames have changed outside the + # command loop (e.g. after a "continue" command), so we show + # the annotations again + breakpoint_annotations(commands, context) + display_annotations(commands, context) + annotation('stack', commands, context, "where") + annotation('variables', commands, context, "info variables") unless + context.dead? + end + end + + def postcmd(commands, context, cmd) + if Debugger.annotate.to_i > 0 + cmd = @last_cmd unless cmd + breakpoint_annotations(commands, context) if + @@Show_breakpoints_postcmd.find{|pat| cmd =~ pat} + display_annotations(commands, context) + if @@Show_annotations_postcmd.find{|pat| cmd =~ pat} + annotation('stack', commands, context, "where") if + context.stack_size > 0 + annotation('variables', commands, context, "info variables") unless + context.dead? + end + if not context.dead? and @@Show_annotations_run.find{|pat| cmd =~ pat} + aprint 'starting' if Debugger.annotate.to_i > 2 + + @debugger_context_was_dead = false + end + end + end + + def postloop(commands, context) + end + + def annotation(label, commands, context, cmd) + print afmt(label) + one_cmd(commands, context, cmd) + ### FIXME ANNOTATE: the following line should be deleted + print "\032\032\n" + end + + def breakpoint_annotations(commands, context) + unless Debugger.breakpoints.empty? and @debugger_breakpoints_were_empty + annotation('breakpoints', commands, context, "info breakpoints") + @debugger_breakpoints_were_empty = Debugger.breakpoints.empty? + end + end + + def display_annotations(commands, context) + return if display.empty? +# have_display = display.find{|d| d[0]} +# return unless have_display and @debugger_displays_were_empty +# @debugger_displays_were_empty = have_display + annotation('display', commands, context, "display") + end + + class State # :nodoc: + attr_accessor :context, :file, :line, :binding + attr_accessor :frame_pos, :previous_line, :display + attr_accessor :interface, :commands + + def initialize + super() + @frame_pos = 0 + @previous_line = nil + @proceed = false + yield self + end + + # FIXME: use delegate? + def errmsg(*args) + @interface.errmsg(*args) + end + + def print(*args) + @interface.print(*args) + end + + def confirm(*args) + @interface.confirm(*args) + end + + def proceed? + @proceed + end + + def proceed + @proceed = true + end + end + end + + class ControlCommandProcessor < Processor # :nodoc: + def initialize(interface) + super() + @interface = interface + @debugger_context_was_dead = true # Assume we haven't started. + end + + def process_commands(verbose=false) + control_cmds = Command.commands.select do |cmd| + cmd.allow_in_control + end + state = State.new(@interface, control_cmds) + commands = control_cmds.map{|cmd| cmd.new(state) } + + unless @debugger_context_was_dead + if Debugger.annotate.to_i > 2 + aprint 'exited' + print "The program finished.\n" + end + @debugger_context_was_dead = true + end + + while input = @interface.read_command(prompt(nil)) + print "+#{input}" if verbose + catch(:debug_error) do + if cmd = commands.find{|c| c.match(input) } + cmd.execute + else + errmsg "Unknown command\n" + end + end + end + rescue IOError, Errno::EPIPE + rescue Exception + print "INTERNAL ERROR!!! #{$!}\n" rescue nil + print $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil + ensure + @interface.close + end + + # The prompt shown before reading a command. + # Note: have an unused 'context' parameter to match the local interface. + def prompt(context) + p = '(rdb:ctrl) ' + p = afmt("pre-prompt")+p+"\n"+afmt("prompt") if + Debugger.annotate.to_i > 2 + return p + end + + class State # :nodoc: + attr_reader :commands, :interface + + def initialize(interface, commands) + @interface = interface + @commands = commands + end + + def proceed + end + + def errmsg(*args) + @interface.print(*args) + end + + def print(*args) + @interface.print(*args) + end + + def confirm(*args) + 'y' + end + + def context + nil + end + + def file + errmsg "No filename given.\n" + throw :debug_error + end + end # State + end +end diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..eb825b8 --- /dev/null +++ b/configure.ac @@ -0,0 +1,12 @@ +AC_INIT(ruby-debug-extra, 0.10.4vc,) +AC_CONFIG_SRCDIR(doc/ruby-debug.texi) +AM_INIT_AUTOMAKE + +## +## Find out where to install the debugger emacs lisp files +## +AM_PATH_LISPDIR +AM_CONDITIONAL(INSTALL_EMACS_LISP, test "x$lispdir" != "x") + +AC_CONFIG_FILES([doc/Makefile emacs/Makefile Makefile]) +AC_OUTPUT diff --git a/doc/.cvsignore b/doc/.cvsignore new file mode 100644 index 0000000..5260245 --- /dev/null +++ b/doc/.cvsignore @@ -0,0 +1,42 @@ +Makefile +Makefile.in +mdate-sh +missing +rdebug-emacs.aux +rdebug-emacs.cp +rdebug-emacs.cps +rdebug-emacs.fn +rdebug-emacs.fns +rdebug-emacs.html +rdebug-emacs.info +rdebug-emacs.ky +rdebug-emacs.log +rdebug-emacs.pdf +rdebug-emacs.pg +rdebug-emacs.pgs +rdebug-emacs.toc +rdebug-emacs.tp +rdebug-emacs.vr +rdoc +ruby-debug.aux +ruby-debug.cp +ruby-debug.cps +ruby-debug.fn +ruby-debug.fns +ruby-debug.html +ruby-debug.info +ruby-debug.ky +ruby-debug.kys +ruby-debug.log +ruby-debug.pdf +ruby-debug.pg +ruby-debug.pgs +ruby-debug.toc +ruby-debug.tp +ruby-debug.vr +ruby-debug.vrs +stamp-1 +stamp-vti +texinfo.tex +version-rdebug-emacs.texi +version.texi diff --git a/doc/.svn/README.txt b/doc/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/doc/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/doc/.svn/dir-prop-base b/doc/.svn/dir-prop-base new file mode 100644 index 0000000..361f890 --- /dev/null +++ b/doc/.svn/dir-prop-base @@ -0,0 +1,47 @@ +K 10 +svn:ignore +V 614 +Makefile +Makefile.in +mdate-sh +missing +rdebug-emacs.aux +rdebug-emacs.cp +rdebug-emacs.cps +rdebug-emacs.fn +rdebug-emacs.fns +rdebug-emacs.html +rdebug-emacs.info +rdebug-emacs.ky +rdebug-emacs.log +rdebug-emacs.pdf +rdebug-emacs.pg +rdebug-emacs.pgs +rdebug-emacs.toc +rdebug-emacs.tp +rdebug-emacs.vr +rdoc +ruby-debug.aux +ruby-debug.cp +ruby-debug.cps +ruby-debug.fn +ruby-debug.fns +ruby-debug.html +ruby-debug.info +ruby-debug.ky +ruby-debug.kys +ruby-debug.log +ruby-debug.pdf +ruby-debug.pg +ruby-debug.pgs +ruby-debug.toc +ruby-debug.tp +ruby-debug.vr +ruby-debug.vrs +stamp-1 +stamp-vti +texinfo.tex +version-rdebug-emacs.texi +version.texi + +END diff --git a/doc/.svn/dir-props b/doc/.svn/dir-props new file mode 100644 index 0000000..361f890 --- /dev/null +++ b/doc/.svn/dir-props @@ -0,0 +1,47 @@ +K 10 +svn:ignore +V 614 +Makefile +Makefile.in +mdate-sh +missing +rdebug-emacs.aux +rdebug-emacs.cp +rdebug-emacs.cps +rdebug-emacs.fn +rdebug-emacs.fns +rdebug-emacs.html +rdebug-emacs.info +rdebug-emacs.ky +rdebug-emacs.log +rdebug-emacs.pdf +rdebug-emacs.pg +rdebug-emacs.pgs +rdebug-emacs.toc +rdebug-emacs.tp +rdebug-emacs.vr +rdoc +ruby-debug.aux +ruby-debug.cp +ruby-debug.cps +ruby-debug.fn +ruby-debug.fns +ruby-debug.html +ruby-debug.info +ruby-debug.ky +ruby-debug.kys +ruby-debug.log +ruby-debug.pdf +ruby-debug.pg +ruby-debug.pgs +ruby-debug.toc +ruby-debug.tp +ruby-debug.vr +ruby-debug.vrs +stamp-1 +stamp-vti +texinfo.tex +version-rdebug-emacs.texi +version.texi + +END diff --git a/doc/.svn/empty-file b/doc/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/doc/.svn/entries b/doc/.svn/entries new file mode 100644 index 0000000..d3e5d42 --- /dev/null +++ b/doc/.svn/entries @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + diff --git a/doc/.svn/format b/doc/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/doc/.svn/format @@ -0,0 +1 @@ +4 diff --git a/doc/.svn/prop-base/.cvsignore.svn-base b/doc/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/Makefile.am.svn-base b/doc/.svn/prop-base/Makefile.am.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/Makefile.am.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/emacs-notes.txt.svn-base b/doc/.svn/prop-base/emacs-notes.txt.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/emacs-notes.txt.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/hanoi.rb.svn-base b/doc/.svn/prop-base/hanoi.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/hanoi.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/primes.rb.svn-base b/doc/.svn/prop-base/primes.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/primes.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/rdebug-emacs.texi.svn-base b/doc/.svn/prop-base/rdebug-emacs.texi.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/rdebug-emacs.texi.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/rdebug.1.svn-base b/doc/.svn/prop-base/rdebug.1.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/doc/.svn/prop-base/rdebug.1.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/doc/.svn/prop-base/ruby-debug.texi.svn-base b/doc/.svn/prop-base/ruby-debug.texi.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/ruby-debug.texi.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/test-tri2.rb.svn-base b/doc/.svn/prop-base/test-tri2.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/test-tri2.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/tri3.rb.svn-base b/doc/.svn/prop-base/tri3.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/tri3.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/prop-base/triangle.rb.svn-base b/doc/.svn/prop-base/triangle.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/prop-base/triangle.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/.cvsignore.svn-work b/doc/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/Makefile.am.svn-work b/doc/.svn/props/Makefile.am.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/Makefile.am.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/emacs-notes.txt.svn-work b/doc/.svn/props/emacs-notes.txt.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/emacs-notes.txt.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/hanoi.rb.svn-work b/doc/.svn/props/hanoi.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/hanoi.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/primes.rb.svn-work b/doc/.svn/props/primes.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/primes.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/rdebug-emacs.texi.svn-work b/doc/.svn/props/rdebug-emacs.texi.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/rdebug-emacs.texi.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/rdebug.1.svn-work b/doc/.svn/props/rdebug.1.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/doc/.svn/props/rdebug.1.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/doc/.svn/props/ruby-debug.texi.svn-work b/doc/.svn/props/ruby-debug.texi.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/ruby-debug.texi.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/test-tri2.rb.svn-work b/doc/.svn/props/test-tri2.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/test-tri2.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/tri3.rb.svn-work b/doc/.svn/props/tri3.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/tri3.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/props/triangle.rb.svn-work b/doc/.svn/props/triangle.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/doc/.svn/props/triangle.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/doc/.svn/text-base/.cvsignore.svn-base b/doc/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..5260245 --- /dev/null +++ b/doc/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1,42 @@ +Makefile +Makefile.in +mdate-sh +missing +rdebug-emacs.aux +rdebug-emacs.cp +rdebug-emacs.cps +rdebug-emacs.fn +rdebug-emacs.fns +rdebug-emacs.html +rdebug-emacs.info +rdebug-emacs.ky +rdebug-emacs.log +rdebug-emacs.pdf +rdebug-emacs.pg +rdebug-emacs.pgs +rdebug-emacs.toc +rdebug-emacs.tp +rdebug-emacs.vr +rdoc +ruby-debug.aux +ruby-debug.cp +ruby-debug.cps +ruby-debug.fn +ruby-debug.fns +ruby-debug.html +ruby-debug.info +ruby-debug.ky +ruby-debug.kys +ruby-debug.log +ruby-debug.pdf +ruby-debug.pg +ruby-debug.pgs +ruby-debug.toc +ruby-debug.tp +ruby-debug.vr +ruby-debug.vrs +stamp-1 +stamp-vti +texinfo.tex +version-rdebug-emacs.texi +version.texi diff --git a/doc/.svn/text-base/Makefile.am.svn-base b/doc/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 0000000..477fc7e --- /dev/null +++ b/doc/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,63 @@ +############################################################################## +# $Id: Makefile.am,v 1.3 2006/12/28 12:34:25 rockyb Exp $ +# Copyright (C) 2007 Rocky Bernstein +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## + +EXT=1 +man1_MANS = rdebug.$(EXT) + +EXTRA_DIST = $(man1_MANS) \ + hanoi.rb primes.rb test-tri2.rb tri3.rb triangle.rb \ + ruby-debug.info ruby-debug.html ruby-debug.pdf + +info_TEXINFOS = ruby-debug.texi rdebug-emacs.texi + +all: $(INFO_DEPS) $(man1_MANS) html pdf + +pdf: ruby-debug.pdf rdebug-emacs.pdf + +txt: ruby-debug.txt rdebug-emacs.txt + +ps: ruby-debug.ps rdebug-emacs.ps + +man: $(man1_MANS) + +html: ruby-debug.html rdebug-emacs.html + +ruby-debug.html: ruby-debug.texi + texi2html $(srcdir)/ruby-debug.texi || true + +rdebug-emacs.html: rdebug-emacs.texi + texi2html $(srcdir)/rdebug-emacs.texi || true + +%.ps.gz: %.ps + gzip -9c $< > $@ + +# Our `texinfo.tex' must reside in the current directory, otherwise +# texi2dvi will use the default. +.texi.pdf: + $(TEXI2PDF) -I $(srcdir) $< + +.texi.dvi: + $(TEXI2DVI) -I $(srcdir) $< + +.dvi.ps: + test -d $(docdir) || mkdir $(docdir) + $(DVIPS) $< -o $@ + +all-formats: pdf dvi txt ps html + +MOSTLYCLEANFILES = rubydb.tgs rubydb.ps.gz rubydb.pdf rubydb.html rubydb_toc.html rubydb_foot.html rubydb-man.html diff --git a/doc/.svn/text-base/emacs-notes.txt.svn-base b/doc/.svn/text-base/emacs-notes.txt.svn-base new file mode 100644 index 0000000..4568791 --- /dev/null +++ b/doc/.svn/text-base/emacs-notes.txt.svn-base @@ -0,0 +1,38 @@ +* rdebug.el is loaded by the user when Emacs is launched. (Should +Rdebug ever be part of Emacs, this should be the items autoloaded by +Emacs.) + +There is a command buffer which is the gud process. There are a number +of "secondary" buffers have in gud-comint-buffer the gud process. The +way we go the other direction from gud process to secondary buffer is +by buffer name. Source buffers don't seem to have a local +gud-comint-buffer variable set but use the global value. Perhaps +source buffer should have their own buffer-local value(s)? + +For each secondary buffer we have things for that specific buffer. In particular: +* frames (rdebug-frames.el) +* output (rdebug-output.el) +* variables (rdebug-varbuf.el) +* watch or display-expressions - (rdebug-watch.el +* breakpoints (rdebug-breaks.el) + +Each specific secondary buffer includes + - setting the buffer up, + - specific commands for that buffer + - the kinds of functions that buffer deals with (e.g. frame + things for the "frame" buffer or breakpoints for the "breakpoints" buffer.) + +* rdebug-gud.el contains things that interface to gdb. Possibly also +things that interface to gdb-ui should be there as well. + +* rdebug-shortkey.el has all the magic that needs to be done to make + shortkey mode work. + +* rdebug-track is all the things to make rdebug-track mode work. + +I have some additions, which deals with *when* certain files are loaded. + +* rdebug-source.el is loaded when the first Ruby source file is loaded +Of course, the name rdebug-source.el is not important, we could rename +it to something else and reuse the name for other source-related +things. diff --git a/doc/.svn/text-base/hanoi.rb.svn-base b/doc/.svn/text-base/hanoi.rb.svn-base new file mode 100644 index 0000000..99c4c10 --- /dev/null +++ b/doc/.svn/text-base/hanoi.rb.svn-base @@ -0,0 +1,35 @@ +#!/usr/bin/ruby + +def hanoi(n,a,b,c) + if n-1 > 0 + hanoi(n-1, a, c, b) + end + puts "Move disk %s to %s" % [a, b] + if n-1 > 0 + hanoi(n-1, c, b, a) + end +end + +i_args=ARGV.length +if i_args > 1 + puts "*** Need number of disks or no parameter" + exit 1 +end + +n=3 + +if i_args > 0 + begin + n = ARGV[0].to_i + rescue ValueError, msg: + print "** Expecting an integer, got: %s" % ARGV[0].to_s + exit 2 + end +end + +if n < 1 or n > 100 + puts "*** number of disks should be between 1 and 100" + exit 2 +end + +hanoi(n, :a, :b, :c) diff --git a/doc/.svn/text-base/primes.rb.svn-base b/doc/.svn/text-base/primes.rb.svn-base new file mode 100644 index 0000000..e94219c --- /dev/null +++ b/doc/.svn/text-base/primes.rb.svn-base @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby +# Enumerator for primes +class SievePrime + @@odd_primes = [] + def self.next_prime(&block) + candidate = 2 + yield candidate + not_prime = false + candidate += 1 + while true do + @@odd_primes.each do |p| + not_prime = (0 == (candidate % p)) + break if not_prime + end + unless not_prime + @@odd_primes << candidate + yield candidate + end + candidate += 2 + end + end +end +SievePrime.next_prime do |prime| + puts prime + break if prime > 10 +end + + diff --git a/doc/.svn/text-base/rdebug-emacs.texi.svn-base b/doc/.svn/text-base/rdebug-emacs.texi.svn-base new file mode 100644 index 0000000..89a5cab --- /dev/null +++ b/doc/.svn/text-base/rdebug-emacs.texi.svn-base @@ -0,0 +1,1030 @@ +\input texinfo @c -*-texinfo-*- +@setfilename rdebug-emacs.info + +@set DBG ruby-debug +@set ttrdebug @code{rdebug} +@set ttDBG @code{@value{DBG}} +@set Emacs @sc{gnu} Emacs + +@set RDEBUG_EMACS_VERSION 0.1 +@include version-rdebug-emacs.texi +@finalout + +@c Karl Berry informs me that this will add straight quotes in +@c typewriter text. +@c See the "Inserting Quote Characters" node in the Texinfo manual +@set txicodequoteundirected +@set txicodequotebacktick + +@c THIS MANUAL REQUIRES TEXINFO 4.0 OR LATER. + +@c This is a dir.info fragment to support semi-automated addition of +@c manuals to an info tree. +@dircategory Programming & development tools. +@direntry +* ruby-debug-emacs: (ruby-debug). Ruby Debugger for GNU Emacs +@end direntry + +@titlepage +@title Debugging with @code{ruby-debug} inside GNU Emacs Version @value{RDEBUG_EMACS_VERSION} +@sp 1 +@subtitle @value{EDITION} Edition +@subtitle @value{UPDATED-MONTH} +@author Rocky Bernstein and Anders Lindgren +@page +@ifset WHERETO +@tex +{\parskip=0pt +\hfill (Send bugs and comments on ruby-debug to fill in...)\par +\hfill {\it Debugging with {\tt ruby-debug}\par +\hfill \TeX{}info \texinfoversion\par +} +@end tex +@end ifset +@end titlepage +@page + +@node Top, Getting started, (dir), (dir) +@top Debugging with ruby-debug under GNU Emacs + +@menu +* Getting started:: +* The Multi-window Mode:: +* Debugger Buffers:: +* Emacs Debugger Commands:: Indexes (nodes containing large menus) +* Emacs Command Index:: An item for each GNU/Emacs command name. +* Emacs Function Index:: An item for each Emacs Function. +* Emacs Key Binding Index:: An item for each Emacs Debugger Command. + +@detailmenu + --- The Detailed Node Listing --- + +Getting started + +* Installation:: How to install this package +* Emacs rdebug:: Invoke the ruby debugger initially +* Emacs shell tracking mode:: Entering rdebug from an existing shell buffer + +Debugger Buffers + +* Debugger Command Buffer:: +* Emacs Source:: Commands from the source script + +Emacs Debugger Commands + +* Emacs Debugger Common Commands:: +* Emacs Debugger Breakpoint Buffer Commands:: +* Emacs Debugger Stack Buffer Commands:: +* Emacs Debugger Variable Buffer Commands:: +* Emacs Debugger Watch Buffer Commands:: +* Emacs GUD Commands:: + +@end detailmenu +@end menu + +This file describes ruby-debug, the Ruby Debugger, +version @value{RDEBUG_EMACS_VERSION} + +This is the @value{EDITION} Edition, @value{UPDATED} +@c Copyright (C) 2007 ... + +@c @node GNU Emacs +@c @chapter Using @code{ruby-debug} from GNU Emacs + + +@cindex @value{Emacs} +A special interface which comes with Ruby that allows you to use +@value{Emacs} to view (and edit) the source files for the program you +are debugging with @value{DBG}. However you must be using at least +version 21 of @value{Emacs}, but with @value{Emacs} version 22 or 23 +there are even more debugging features available. @code{M-x +show-emacs-version} inside @value{Emacs} will tell you what version you +are running. + +This package provide a full-fledged debugging environment, on par with +modern integrated development environments. Once the debugger has been +activated, the Emacs frame is divided into a number of dedicated +debugger windows.@footnote{If you are an @value{Emacs} traditionalist, +you can, of course, run this package with only a shell and source +buffer} + +This package comes with a number of predefined window layouts. It is +fully customizable so you can create your own. + +@c ------------------------------------------------------------------- + + +@node Getting started, The Multi-window Mode, Top, Top +@chapter Getting started + +@menu +* Installation:: How to install this package +* Emacs rdebug:: Invoke the ruby debugger initially +* Emacs shell tracking mode:: Entering rdebug from an existing shell buffer +* Configurating this package:: Introducing the configure system +@end menu + +@node Installation, Emacs rdebug, Getting started, Getting started +@section Installation + +To use this interface, load the file @code{rdebug.el}. This file is a +light-weight file, basically it only contains a handful of +@code{autoload} directives. + +For example, you can place the following in your @code{~/.emacs} file: + +@smallexample + (require 'rdebug) +@end smallexample + +In addition, you must have Ruby and ruby-debug installed. + + +@node Emacs rdebug, Emacs shell tracking mode, Installation, Getting started +@section Emacs rdebug + +Use the command @kbd{M-x rdebug} in @sc{gnu} Emacs to start debugging. +Give the executable file you want to debug as an argument. Make sure +to use the version that comes with this package as this is newer than +that supplied with @value{Emacs}. + +The @kbd{rdebug} command starts @value{DBG} as a subprocess of Emacs, +with input and output through a newly created Emacs buffer. + +Using @value{DBG} under Emacs is just like using @value{DBG} +normally except for two things: + +@itemize @bullet +@item +All ``terminal'' input and output goes through the GNU Emacs buffer. +@end itemize + +This applies both to @value{DBG} commands and their output, and to the input +and output done by the program you are debugging. + +This is useful because it means that you can copy the text of previous +commands and input them again; you can even use parts of the output +in this way. + +All the facilities of GNU Emacs' Shell mode are available for interacting +with your script. In particular, you can send signals the usual +way---for example, @kbd{C-c C-c} for an interrupt, @kbd{C-c C-z} for a +stop. + +@node Emacs shell tracking mode, Configurating this package, Emacs rdebug, Getting started +@section Entering rdebug from an existing shell buffer + +Many times it's not feasible to enter the debugger from the outset. +Instead a call to the debugger is put inside the program. + +@c See @xref{Unit Testing Session}. + +It is also possible in GNU emacs to use a (``comint'') shell and set a +mode to watch for @value{DBG} prompts and track the source code in +another window. @xref{Interactive Shell, , Shell, Emacs, The @value{Emacs} +Manual}. + +To enable, this run @kbd{M-x turn-on-rdebug-track-mode}. There is some +overhead involved in scanning output, so if you are not debugging Ruby +programs you probably want to turn this off which can be done via the +@code{M-x turn-off-rdebugtrack} command. + + +@node Configurating this package, , Emacs shell tracking mode, Getting started +@section Configurating this package + +In this manual we present a number of @value{Emacs} lisp variables and +functions that you can use to configure the debugger interface. In +addition, you can use the @value{Emacs} @emph{customize} system, see the +@kbd{ } menu item. + +@c ------------------------------------------------------------------- + +@node The Multi-window Mode, Debugger Buffers, Getting started, Top +@chapter Multi-window + +In the multi-window debugger mode, a number of buffers are visible when +the debugger starts. This chapter will describe each of them, in +addition it will describe the features associated with the multi-window +mode. + +The default multi-window layout looks like the following: + +@verbatim ++----------------------------------------------------------------------+ +| Toolbar | ++-----------------------------------+----------------------------------+ +| | | +| Debugger shell | Variables buffer | +| | | ++-----------------------------------+----------------------------------+ +| | | +| Source buffer | Output buffer | +| | | ++-----------------------------------+----------------------------------+ +| | | +| Stack buffer | Breakpoints buffer | +| | | ++-----------------------------------+----------------------------------+ +@end verbatim + +@section Activating Multi-window mode + +The variable @code{rdebug-many-windows} controls if multi-window mode +should be used, it is enabled by default. When starting the debugger +using the @code{M-x rdebug} mode the command line option @code{--emacs +3} must be specified (this is also the default). + +When attaching to an already running debugger process, you must give the +debugger command @kbd{set annotate 3}. + +@section Window Layouts + +When the debugger is started, the original window layout of +@value{Emacs} is replaced with the window layout of the debugger. You +can switch back and forth between the original window layout and the +debugger layout using +@kbd{M-x rdebug-display-original-window-configuration} and +@kbd{M-x rdebug-display-debugger-window-configuration}. + +If, for some reason, the debugger layout has been garbled you can +restore it to the original state using @kbd{M-x +rdebug-restore-debugger-window-layout}. + +The debugger provides a number of different window layouts. The easies +way to try them out is to use the menu @kbd{ +} and select any in the section starting with @code{Standard}. + + +@section The buffers + +All buffers in this section share a set of commands for common debugger +operations and for switching between buffers. In addition, each buffer +has got a set of dedicated commands. + +All debugger buffers, with the exception of source and the debugger +shell window, are called @emph{secondary buffers}. + +@subsection Keybindings for all Debugger Windows + +The debugger provides key-bindings that work in all debugger windows, +including Ruby source buffers. The key bindings are designed to match +keys of commonly used debugger environments. + +The variable @code{rdebug-populate-common-keys-function} can be assigned +to a function that should bind the keys use. Three functions are +provided @code{rdebug-populate-common-keys-standard}, +@code{...-eclipse}, and @code{...-netbeans}. + +@multitable @columnfractions 0.4 0.2 0.2 0.2 +@headitem Command @tab Standard @tab Eclipse @tab Netbeans +@item Run @tab f5 @tab @tab +@item Quit @tab S-f5 @tab @tab +@item Toggle Breakpoint @tab f9 @tab @tab +@item Enable/Disable Breakpoint @tab C-f9 @tab S-C-b @tab S-f8 +@item Step over @tab f10 @tab f6 @tab f8 +@item Step into @tab f11 @tab f5 @tab f7 +@item Step out @tab S-f11 @tab f7 @tab M-S-f7 + +@end multitable + + + +@subsection Keybindings for Secondary Buffers + +The following commands are available in all secondary windows. + +Capital letters move between secondary buffers as mentioned above (jump +to if visible or replace a secondary if not). + +@table @kbd +@item SPACE +step (edebug compatible) +@item < +Up in the stack trace +@item > +Down in the stack trace +@item ? +Help +@item B +Display breakpoints buffer +@item C +Display command buffer +@item O +Display program output +@item S +Display source window +@item T +Display stack trace buffer +@item V +display variables buffer +@item W +display watch buffer +@item b +Set breakpoint +@item c +Continue (i.e. run) +@item d +Remove breakpoint +@item f +Finish (i.e. step out of the current function) +@item n +Next (i.e. step into function) +@item p +print +@item q +Quit +@item r +Restart +@item s +Step (i.e. step over function) +@end table + +You can use the same commands in the source buffer if you enable +@code{rdebug-short-key-mode}. The best way to do this is to add the +following to your init file: + +@smallexample + (add-hook 'rdebug-mode-hook 'rdebug-turn-on-short-key-mode) +@end smallexample + + + +@subsection The Debugger Shell Buffer + +The @emph{debugger shell window} is the main communication channel +between @value{DBG} and @value{Emacs}. You can use the shell to issue +debugger commands directly. In addition, any @value{Emacs} debugger +command you issue will be translated into shell commands, and the output +will be parsed. + +It is the ambition that the @value{Emacs} debugger interface should be +in a state where the debugger shell window would not need to be visible. + +@subsection The Source Buffer + +The @emph{source buffers} (or buffers) contains the actual Ruby source +code that is being debugged. A small arrow in the left fringe displays +the current line. Active breakpoints are displayed as red dots and +passive as grey. + +@subsection The Output Buffer + +The @emph{output buffer} displays any output the debugged program emits. + +The option @code{rdebug-use-separate-io-buffer} controls if the output +buffer should be used, or if the output would go into the debugger shell +buffer. + +@subsection The Variables Buffer + +In this buffer, local and object variables are displayed. The values of +the variables can be edited. + +@table @kbd +@item RET +Edit the value +@item e +Print the value +@item x +Pretty-print the value +@end table + +@subsection The Stack Trace Buffer + +The @emph{stack trace} buffer displays the function that is currently +being debugger, the function that called it, etc., all the way up to the +originally called function. + +You can navigate in the stack trace buffer in order to see the source of +any function in the call chain. The Variables buffer will also be +updated to reflect the local variables of that function. + +@table @kbd +@item RET +Select a function to display +@item +Go to a stack frame +@end table + +@subsection The Watch Buffer + +The @emph{Watch Buffer} can display arbitrary expressions, including, +but not limited to, global variables. + +@table @kbd +@item a +Add a watch expression +@item C-d, d +Delete a watch expression +@item RET, e +Edit a watch expression +@item +Go to the expression +@end table + +@subsection The Breakpoints Buffer + +The @emph{Breakpoints Buffer} displays all breakpoints that currently are +defined and shows if they are enabled or disabled. + +@table @kbd +@item t +Toggle a breakpoint between enabled and disabled +@item i +Add a breakpoint condition +@item ret +Goto a breakpoint +@item C-d +Delete a breakpoint +@item +Go to the expression +@end table + +@subsection The Help Buffer + +The @emph{Help Buffer} is displayed whenever you press @code{?}. It will +display a help text on the available debugger commands and commands to +navigate between the buffers. + + +@c ------------------------------------------------------------------- + +@node Debugger Buffers, Emacs Debugger Commands, The Multi-window Mode, Top +@chapter Debugger Buffers + +@menu +* Debugger Command Buffer:: +* Emacs Source:: Commands from the source script +@end menu + +@node Debugger Command Buffer, Emacs Source, Debugger Buffers, Debugger Buffers +@section Emacs Debugger Command buffer + +Each time @value{DBG} displays a stack frame, Emacs automatically finds the +source file for that frame and puts an arrow (@samp{=>}) at the +left margin of the current line. Emacs uses a separate buffer for +source display, and splits the screen to show both your @value{DBG} session +and the source. + +Explicit @value{DBG} @code{list} or search commands still produce output as +usual, but you probably have no reason to use them from GNU Emacs. + +@quotation +@emph{Warning:} If the directory where your script resides is not your +current directory, it can be easy to confuse Emacs about the location of +the source files, in which case the auxiliary display buffer does not +appear to show your source. @value{DBG} can find programs by searching your +environment's @code{PATH} variable, so the @value{DBG} input and output +session proceeds normally; but Emacs does not get enough information +back from @value{DBG} to locate the source files in this situation. To +avoid this problem, either start @value{DBG} mode from the directory where +your script resides, or specify an absolute file name when prompted for the +@kbd{M-x gdb} argument. + +A similar confusion can result if you use the @value{DBG} @code{file} command to +switch to debugging a program in some other location, from an existing +@value{DBG} buffer in Emacs. +@end quotation + +@noindent +(preceded by @kbd{M-:} or @kbd{ESC :}, or typed in the @code{*scratch*} buffer, or +in your @file{.emacs} file). + +In the @value{DBG} I/O buffer, you can use the Emacs commands listed +below in addition to the standard Shell mode commands. The I/O buffer +name name is usually @code{*gud-}@emph{script-name}@code{*}, where +@emph{script-name} is the name of the script you are debugging. + +Many of the commands listed below are also bound to a second key +sequence which also can be used in the also be used in the source +script. These are listed in @ref{Emacs Source}. + +In secondary buffers many commands are available the corresponding +final keystroke. For example @code{C-c n} in a secondary buffer is +@code{n}. + +@table @kbd +@item C-h m +Describe the features of Emacs' @value{DBG} Mode. + +@item C-x C-a C-b (gud-break) +@pindex C-x C-a C-b (gud-break) +Set breakpoint at current line. + +@item C-x C-a C-d (gud-remove) +@pindex C-x C-a C-d (gud-remove) +Remove breakpoint at current line. + +@item C-x C-a C-l (gud-refresh) +@pindex C-x C-a C-d (gud-refresh) +Fix up a possibly garbled display, and redraw the arrow. + +@item C-c RET (comint-copy-old-input) +@pindex C-c RET (comint-copy-old-input) +Insert after prompt old input at point as new input to be edited. +Calls `comint-get-old-input' to get old input. + +@item C-c n (gud-next) +@pindex C-c n (gud-next) +Step one line, skipping functions. (Step over). + +@item C-x C-a C-o (comint-delete-output) +@pindex C-c n (comint-delete-output) +Delete all output from interpreter since last input. Does not delete +the prompt. + +@item C-x C-a C-r (gud-cont) + +@item C-c SPC (gud-step @var{arg}) +@pindex C-c SPC (gud-step @var{arg}) +@itemx C-x C-a C-s (gud-step @var{arg}) +@pindex C-x C-a C-s (gud-step @var{arg}) +Step one source line. Same as @value{DBG} @code{step} command. The +@value{Emacs} command name is @code{gud-step} and @code{C-x C-a C-s} +is an alternate binding which can be used in the source +script. +@c @xref{Step}. + +With a numeric argument, run that many times. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + + +@item C-x C-a C-t (gud-tbreak @var{arg}) +Set temporary breakpoint at current line. + +@item C-x C-a C-w (backward-kill-word) +@item C-x C-a C-x (comint-get-next-from-history) +@item C-x C-a C-z (comint-stop-subjob) +Stop the current subjob. +This command also kills the pending input +between the process mark and point. + +WARNING: if there is no current subjob, you can end up suspending +the top-level process running in the buffer. If you accidentally do +this, use M-x comint-continue-subjob to resume the process. (This +is not a problem with most shells, since they ignore this signal.) + +@item C-x C-a C-\ (comint-quit-subjob) +Send quit signal to the current subjob. +This command also kills the pending input +between the process mark and point. + +@item C-c + (gud-step-plus) +Run @code{step+}. + +@item C-c . (comint-insert-previous-argument @var{index}) +Insert the @emph{index-th} argument from the previous Comint command-line at point. +Spaces are added at beginning and/or end of the inserted string if +necessary to ensure that it's separated from adjacent arguments. +Interactively, if no prefix argument is given, the last argument is inserted. +Repeated interactive invocations will cycle through the same argument +from progressively earlier commands (using the value of index specified +with the first command). + +@item C-c < (gud-up) +Go up a stack frame. With a numeric argument, go up that many +stack frames. Same @value{DBG} @code{up} command. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + +@item C-c > (gud-down) +Go down a stack frame. Same as @value{DBG} @code{down}. +With a numeric argument, go down that many stack frames. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + +@item C-c ? (rdebug-display-secondary-window-help-buffer) +Display the rdebug help buffer. + +@item C-c B (rdebug-display-breakpoints-buffer) +Display the rdebug breakpoints buffer. + +@item C-x C-a C (rdebug-display-cmd-buffer) +Display the rdebug command buffer. + +@item C-c O (rdebug-display-output-buffer) +Display the rdebug output buffer. + +@item C-c R (gud-run) +@itemx C-c r (gud run) +Restart or run the script. Same as @value{DBG} @code{run} command. + +@item C-c S (gud-source-resync) +@item C-c T (rdebug-display-stack-buffer) +Display the rdebug stack buffer. +@item C-c V (rdebug-display-variables-buffer) +Display the rdebug variables buffer. + +@item C-c W (rdebug-display-watch-buffer) +Display the rdebug watch buffer. + +@item C-c f (gud-finish @var{arg}) +@pindex C-c f (gud-finish @var{arg}) +Finish executing current function. + +@itemx C-x C-a C-f (gud-finish) +@pindex C-x C-a C-f (gud-finish) +Finish executing current function. The same as @value{DBG} +@code{finish} command. +@c @xref{Finish}. + +@item C-c n (gud-next) +@pindex C-c n (gud-next) +Execute to next source line in this function, skipping all function +calls. Same as @value{DBG} @code{next} command. +@c @xref{Next}. + +With a numeric argument, run that many times. +@c @xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} Manual}. + +@item C-c q (gud-quit) + +@item C-x C-a C-l +Resynchronize the current position with the source window. The +@value{Emacs} command name is @code{gud-refresh} and @code{C-x C-a +C-l} is an alternate binding which also can be used in the source script. + +@item C-c a +Shows argument variables (e.g.@: @code{$1}, @code{$2}) of the current +stack frame. Same as @value{DBG} @code{info args} command. The +@value{Emacs} command name is @code{gud-args} and @code{C-x C-a a} is +an alternate binding which also can be used in the source script. + +@item C-c T +Show stack trace. Same as @value{DBG} @code{where} command. The +@value{Emacs} command name is @code{gud-where} and @code{C-x C-a T} is +an alternate binding which can be used in the source +script. +@c @xref{Backtrace}. + +@end table + +In any source file, the Emacs command @kbd{C-x SPC} (@code{gud-break}) +tells @value{DBG} to set a breakpoint on the source line point is on. + +If you accidentally delete the source-display buffer, an easy way to get +it back is to type the command @code{frame} in the @value{DBG} buffer, to +request a frame display; when you run under Emacs, this recreates +the source buffer if necessary to show you the context of the current +frame. + +The source files displayed in Emacs are in ordinary Emacs buffers +which are visiting the source files in the usual way. You can edit +the files with these buffers if you wish; but keep in mind that @value{DBG} +communicates with Emacs in terms of line numbers. If you add or +delete lines from the text, the line numbers that @value{DBG} knows cease +to correspond properly with the code. + +@xref{Debugger Operation, , , Emacs, The @value{Emacs} +Manual}. + +@node Emacs Source, , Debugger Command Buffer, Debugger Buffers +@section Commands from the source script + +@table @kbd +@item C-x SPC + +tells @value{DBG} to set a breakpoint on the source +line point is on. (@code{gud-break}) + +@item C-x C-a t + +@code{gud-linetrace} + +@item C-x C-a C-f +Restart or run the script. Same as @value{DBG} @code{run} command. The +@value{Emacs} command name is @code{gud-finish}. In the corresponding +I/O buffer, @code{C-c R} is an alternate binding. + +@item C-x C-a T +Show stack trace. Same as @value{DBG} @code{where} command. In the +corresponding I/O buffer, @code{C-c T} is an alternate +binding. +@c @xref{Backtrace}. + +@item C-x C-a < + +Go up a stack frame. With a numeric argument, go up that many +stack frames. Same @value{DBG} @code{up} command. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} Manual}. + +The @value{Emacs} command name is @code{gud-up}. In the corresponding +I/O buffer, @code{C-c <} is an alternate binding. + +@item C-x C-a > + +Go down a stack frame. Same as @value{DBG} @code{down}. +With a numeric argument, go down that many stack frames. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + +The @value{Emacs} command name is @code{gud-down}. In the +corresponding I/O buffer, @code{C-c >} is an alternate binding. + +@item C-x C-a C-t + +@code{gud-tbreak} + +@item C-x C-a C-s + +Step one source line. Same as @value{DBG} @code{step} +command. +@c @xref{Step}. + +With a numeric argument, run that many times. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + +The @value{Emacs} command name is @code{gud-step}. In the +corresponding I/O buffer, @code{C-x C-a C-s} is an alternate binding. + +@item C-x C-a C-e + +@code{gud-statement} + +@item C-x C-a R +Restart or run the script. Same as @value{DBG} @code{run} command. The +@value{Emacs} command name is @code{gud-run}. In the corresponding I/O +buffer, @code{C-c R} is an alternate binding. + +@item C-x C-a C-d +Delete breakpoint. @code{gud-remove} + +@item C-x C-a C-p + +@code{gud-print} + +@item C-x C-a C-n + +Execute to next source line in this function, skipping all function +calls. Same as @value{DBG} @code{next} command. With a numeric +argument, run that many times. @xref{Arguments, , Numeric Arguments, +Emacs, The @value{Emacs} Manual}. + +The @value{Emacs} command name is @code{gud-next}. In the +corresponding I/O buffer, @code{C-x C-a C-n} is an alternate binding. + +@item C-x C-a f C-f + +@code{gud-finish} + +@item C-x C-a C-r +Continue execution of your script Same as @value{DBG} @code{continue} +command. The @value{Emacs} command name is @code{gud-cont}. In the +corresponding I/O buffer, @code{C-x C-a C-r} is an alternate binding. +@c See @ref{Continue}. + +@item C-x C-a C-b + +@code{gud-break} + +@item C-x C-a a + +@code{gud-args} +Shows argument variables (e.g.@: @code{$1}, @code{$2}) of the current +stack frame. Same as @value{DBG} @code{info args} command. The +@value{Emacs} command name is @code{gud-args}. In the corresponding +I/O buffer, @code{C-c a} is an alternate binding which also can be +used in the source script. + +@item C-x C-a C-l +Move to current position in this source window. The @value{Emacs} +command name is @code{gud-refresh}. In the corresponding I/O buffer, +@code{C-x C-a C-l} is an alternate binding. + +@end table + +@node Emacs Debugger Commands, Emacs Command Index, Debugger Buffers, Top +@chapter Emacs Debugger Commands + +@menu +* Emacs Debugger Common Commands:: +* Emacs Debugger Breakpoint Buffer Commands:: +* Emacs Debugger Stack Buffer Commands:: +* Emacs Debugger Variable Buffer Commands:: +* Emacs Debugger Watch Buffer Commands:: +* Emacs GUD Commands:: +@end menu + +@node Emacs Debugger Common Commands, Emacs Debugger Breakpoint Buffer Commands, Emacs Debugger Commands, Emacs Debugger Commands +@section Emacs Debugger Common Commands + +The commands in this section are used to make a secondary buffer +visible. If the buffer doesn't exist, nothing is done. +The way the buffer is made visible is follows the following +rules tried in order: + +@enumerate +@item +If the buffer doesn't exist, do nothing. +@item +If the buffer is already displayed, switch to it. +@item +If the current buffer is a +secondary buffer, bury it replacing with the requested +buffer. +@item +If there is secondary buffer visible, that +is replaced instead. +@item +Just pick a visible buffer to bury and replace. + @end enumerate + +The commands are also have key bindings that end in an uppercase +letter. This letter is given in parenthesis. When in one of the +secondary buffers, the uppercase letter is bound to the command as well. + +@table @kbd + +@item (rdebug-display-breakpoints-buffer) (@kbd{B}) +@findex rdebug-display-breakpoints-buffer (@kbd{B}) +Display the rdebug breakpoints buffer. Bound to: @kbd{C-x C-a B}, +@kbd{ }. Secondary buffers: +@kbd{O}. + +@item (rdebug-display-cmd-buffer) (@kbd{C}) +@findex rdebug-display-cmd-buffer (@kbd{C}) +Display the debugger command buffer. + +Bound to: @kbd{C-x C-a C}, @kbd{ }. + +@item (rdebug-display-output-buffer) (@kbd{O}) +@findex rdebug-display-output-buffer (@kbd{?}) +Display the debugger output buffer. + +Bound to: @kbd{C-x C-a O}, @kbd{ +}. Secondary buffers: @kbd{O}. + +@item (rdebug-display-secondary-window-help-buffer) (@kbd{?}) +@findex rdebug-display-secondary-window-help-buffer (@kbd{?}) + +@item (rdebug-display-stack-buffer) (@kbd{T}) +@findex rdebug-display-stack-buffer (@kbd{T}) +Display the debugger stack buffer. Bound to: @kbd{C-x C-a T}, +@kbd{ }. Secondary buffers: @kbd{T}. + +@item (rdebug-display-variables-buffer) (@kbd{V}) +@findex rdebug-display-variables-buffer (@kbd{V}) +Display the debugger variables buffer. Bound to: @kbd{C-x C-a V}, +@kbd{ }. Secondary buffers: +@kbd{V}. + +@item (rdebug-display-watch-buffer) (@kbd{W}) +@findex rdebug-display-watch-buffer (@kbd{W}) +Display the debugger variables buffer. Bound to: @kbd{C-x C-a W}, +@kbd{ }. Secondary buffers: @kbd{V}. + +@item (rdebug-display-debugger-window-configuration) +@findex rdebug-display-debugger-window-configuration +Display the current layout of windows of the rdebug Ruby debugger. +@item (rdebug-display-original-window-configuration) +@findex rdebug-display-original-window-configuration +Display the layout of windows prior to starting the rdebug Ruby +debugger. This function is called upon quitting the debugger and +@var{rdebug-many-windows} is not nil. +@item (rdebug-goto-entry-n) +@findex rdebug-goto-entry-n +Breakpoints, Display expressions and Stack Frames all have +numbers associated with them which are distinct from line +numbers. In a secondary buffer, this function is usually bound to +a numeric key. which will position you at that entry number. To +go to an entry above 9, just keep entering the number. For +example, if you press 1 and then 9, you should jump to entry +1 (if it exists) and then 19 (if that exists). Entering any +non-digit will start entry number from the beginning again. +@item (rdebug-quit) - q +@findex rdebug-quit (q) +Kill the debugger process associated with the buffer. + +When @var{rdebug-many-windows} is active, the original window layout is +restored. +@item (rdebug-restore-windows) +@findex rdebug-restore-windows +Display the initial ruby debugger window layout. + +@end table + + +@node Emacs Debugger Breakpoint Buffer Commands, Emacs Debugger Stack Buffer Commands, Emacs Debugger Common Commands, Emacs Debugger Commands +@section Emacs Debugger Breakpoint Buffer Commands + +@table @kbd +@item (rdebug-goto-breakpoint) +@findex rdebug-goto-breakpoint +@item (rdebug-goto-breakpoint-mouse) +@findex rdebug-goto-breakpoint-mouse +@item (rdebug-breakpoints-mode) +@findex rdebug-breakpoints-mode +Major mode for displaying breakpoints in a secondary window. Uses +@var{rdebug-breakpoints-mode-map}. +@end table + +@node Emacs Debugger Stack Buffer Commands, Emacs Debugger Variable Buffer Commands, Emacs Debugger Breakpoint Buffer Commands, Emacs Debugger Commands +@section Emacs Debugger Stack Buffer Commands + +@table @kbd +@item (rdebug-goto-stack-frame) +@findex rdebug-goto-stack-frame +@item (rdebug-frames-mode) +@findex rdebug-frames-mode +Major mode for displaying the stack trace. Uses +@var{rdebug-frames-mode-map}. +@end table + +@node Emacs Debugger Variable Buffer Commands, Emacs Debugger Watch Buffer Commands, Emacs Debugger Stack Buffer Commands, Emacs Debugger Commands +@section Emacs Debugger Variable Buffer Commands + +@table @kbd +@item (rdebug-variables-edit) +@findex rdebug-variables-edit +@end table + +@node Emacs Debugger Watch Buffer Commands, Emacs GUD Commands, Emacs Debugger Variable Buffer Commands, Emacs Debugger Commands +@section Emacs Debugger Watch Buffer Commands + +@table @kbd +@item (rdebug-watch-add) +@findex rdebug-watch-add +Add a display expression. +@item (rdebug-watch-delete) +@findex rdebug-watch-delete +Delete a display expression. +@item (rdebug-watch-edit) +@findex rdebug-watch-edit +Edit a display expression. +@item (rdebug-watch-mode) +@findex rdebug-watch-mode +Major mode for displaying the display expressions. Uses +@var{rdebug-watch-mode-map}. +@end table + +@node Emacs GUD Commands, , Emacs Debugger Watch Buffer Commands, Emacs Debugger Commands +@section Emacs Debugger GUD Commands + +@table @kbd +@item (comint-copy-old-input) +@findex comint-copy-old-input +Insert after prompt old input at point as new input to be edited. +Calls `comint-get-old-input' to get old input. +@item (comint-delete-output) +@findex comint-delete-output +Delete all output from interpreter since last input. +Does not delete the prompt. +@item (gud-break) +@findex gud-break +Set a breakpoint on the source line point is on. +@item (gud-cont) - c +@findex gud-cont (c) +Continue execution. +@item (gud-next) - n +@findex gud-next (n) +Step one line, skipping functions. (Step over). +@item (gud-refresh) +@findex gud-refresh +Fix up a possibly garbled display, and redraw the arrow. +@item (gud-remove) +@findex gud-remove +Remove breakpoint at current line. +@item (gud-step) - s +@findex gud-step (s) +Step one statement. (Step into) +@item (gud-step-plus) - + +@findex gud-step-plus (+) +Run @code{step+}---like @code{gud-step} but ensure we go to a new +line. +@item (gud-tbreak @var{arg}) +@findex gud-tbreak +Set temporary breakpoint at current line. +@end table + +@node Emacs Command Index, Emacs Function Index, Emacs Debugger Commands, Top +@unnumbered Emacs Command Index +@printindex pg + +@node Emacs Function Index, Emacs Key Binding Index, Emacs Command Index, Top +@unnumbered Emacs Function Index +@printindex fn + +@node Emacs Key Binding Index, , Emacs Function Index, Top +@unnumbered Key Binding Index +@printindex ky + +@tex +% I think something like @colophon should be in texinfo. In the +% meantime: +\long\def\colophon{\hbox to0pt{}\vfill +\centerline{The body of this manual is set in} +\centerline{\fontname\tenrm,} +\centerline{with headings in {\bf\fontname\tenbf}} +\centerline{and examples in {\tt\fontname\tentt}.} +\centerline{{\it\fontname\tenit\/},} +\centerline{{\bf\fontname\tenbf}, and} +\centerline{{\sl\fontname\tensl\/}} +\centerline{are used for emphasis.}\vfill} +\page\colophon +% Blame: doc@cygnus.com, 1991. +@end tex + +@bye diff --git a/doc/.svn/text-base/rdebug.1.svn-base b/doc/.svn/text-base/rdebug.1.svn-base new file mode 100644 index 0000000..e004166 --- /dev/null +++ b/doc/.svn/text-base/rdebug.1.svn-base @@ -0,0 +1,241 @@ +.\" $Id$ +.TH rdebug 1 +.SH NAME +rdebug \- Fast Ruby debugger +.SH SYNOPSIS +.B rdebug +[debugger-options] +rdebug +[script-options...] +.SH "DESCRIPTION" +This manual page documents briefly the +.BR rdebug +command. +.PP +.B rdebug +is a fast implementation of the standard Ruby debugger debug.rb. It +is implemented by utilizing a Ruby C API hook, allows for remote +debugging and can be used as the Ruby debugger backend interface for a +development environment. +.PP +The commands generally follow gdb's command set unless there's good +reason not to. + +.PP +rdebug can do four main kinds of things (plus other things in support of +these) to help you catch bugs in the act: + +.TP +\ \ \ \(bu +Start or restart your Ruby script, specifying arguments that might +affect its behavior. + +.TP +\ \ \ \(bu +Make your program stop at various points possibly determined by +specified conditions. + +.TP +\ \ \ \(bu +Examine what has happened when your program has stopped. + +.TP +\ \ \ \(bu +Change things in your program, so you can experiment with correcting the +effects of one bug and go on to learn about another. +.PP + +Here are some of the most frequently-needed commands: +.TP +.B break \fR[\|\fIfile\fB:\fIline\fR\fR|\fIclass.method\fR] \fR[if \fIexpr\fR] +\& +Set a breakpoint at \c +.I class.method\c +\& or at the specified file and line. +.TP +.B continue \fR[\fIline\fR] +Continue running your program (after stopping, e.g. at a +breakpoint). If a line is given a one-time breakpoint is set there. +.TP +.B delete \fR[\fIbreakpoint-numbers\fR] +\& +Delete breakpoints by number. If no number is given delete all breakpoints. +.TP +.B down \fR[\|\fIcount\fR\|] +Move down one block frame. If count is given move up that many frames. A negative number +goes the other direction and is like the up command +.TP +.B finish +Run until the completion of the current function or method. +.TP +.BI frame " frame-number" +Set the stack frame to \fIframe-number\fR for purposes of examinine local variables. For positioning relative to the current frame, use +.B up +or +.B down. A negative number starts counting from the other end. +.TP +.B help \fR[\|\fIname\fR\|] +Show information about rdebug command \c +.I name\c +\&, or general information +about using rdebug. +.TP +.B info \fR[\|\fIname\fR\|] +Get the various information usually about the debugged program. +.TP +.B irb \fIcommand\fR +Run an interactive ruby shell (irb) using the current environment. +.TP +.B list \fR[\|\fIfile\fB:\fIline\fR|\fIfunction] +type the text of the program in the vicinity of where it is presently stopped +or at the specified function or file and line. +.TP +.B next \fR[\|\fIcount\fR\|] +Execute next program line(s) (after stopping); step \c +.I over\c +\& any +function calls in the line. +.TP +.BI pp " expr"\c +\& +Pretty print the value of an expression. +.TP +.BI print " expr"\c +\& +Display the value of an expression. +.TP +.BI ps " expr"\c +\& +Print an array as a columized sorted list. +.TP +.B quit +Exit from the debugger. +.TP +.B run \fR[\|\fIarglist\fR\|] +(Re)start your program (with \c +.I arglist\c +\&, if specified). If you want the debugger to get reloaded, use +.B restart +instead. +.TP +.B set +Modify parts of the debugger environment. +.TP +.B show +See the debugger environment settings +.TP +.BI source " filename"\c +\& +Read and execute the lines in file \fIfilename\fR as a series of debugger +commands. +.TP +.B step \fR[\|\fIcount\fR\|] +Execute next program line(s) (after stopping); step \c +.I into\c +\& any +function calls in the line. +.TP +.B up \fR[\|\fIcount\fR\|] +Move up one block frame. If count is given move up that many frames. A negative number +goes the other direction and is like the down command +.TP +.B where \fR[\|\fIcount\fR\|] +Display all or \fIcount\fR items of the program stack. +.PP +For full details on rdebug, see \c +http://rubyforge.org/projects/ruby-debug/ +.SH OPTIONS +.PP +.TP 10 +.TP +.B \-A | \-\-annotate LEVEL +Set gdb-style annotation to LEVEL, a number. Additional information is output +automatically when program state is changed. This can be used by +front-ends such as GNU Emacs to post this updated information without +having to poll for it. +.TP +.B \-\-client +Connect to a remote debugger. Used with another rdebug invocation using \-\-server. +See also \-\-host and \-\-cport options +.TP +.B \-\-cport=PORT +Port used for control commands. +.TP +.B \-d | \-\-debug +Set $DEBUG true. +.TP +.B \-\-emacs +Activates full GNU Emacs mode. Is the equivalent of setting the +options \-\-emacs\-basic, \-\-annotate=3, \-\-no-stop, \-\-no\-control +and \-\-post\-mortem. +.TP +.B \-\-emacs-basic +Activates GNU Emacs mode. Debugger prompts are prefaced with two octal +032 characters. +.TP +.B \-h | \-\-host=HOST +Host name used for remote debugging. +.TP +.B \-I | \-\-include PATH +Add PATH to $LOAD_PATH +.TP +.B \-m | \-\-post-mortem +Activate post-mortem mode. +.TP +.B \-\-no-control +Do not automatically start control thread. +.TP +.B \-\-no\-stop +Do not stop when script is loaded. +.TP +.B \-p | \-\-port=PORT +Host name used for remote debugging. +.TP +.B \-r | \-\-require SCRIPT +Require the library, before executing your script. +.TP +.B \-\-script FILE +Name of the script file to run. +.TP +.B \-x | \-\-trace +Show lines before executing them. +.TP +.B \-\-no\-quit +Do not quit when script terminates. Instead rerun the program. +.TP +.B \-\-version +Show the version number and exit. +.TP +.B \-\-verbose +Turn on verbose mode. +.TP +.B \-\-v +Print the version number, then turn on verbose mode if a script name +is given. If no script name is given just exit after printing the +version number. +.TP +.B \-\-nx +Don't execute commands found in any initialization files, e.g. .rdebugrc. +.TP +.B \-\-keep-frame-binding +Keep frame bindings. +.TP +.B \-\-script=FILE +Name of the script file to run +.B \-s | \-\-server +Listen for remote connections. Another rdebug session accesses using the \-\-client option. +See also the \-\-host, \-\-port and +\-\-cport options +.TP +.B \-w | \-\-wait +Wait for a client connection, implies -s option. +.TP +.B \-\-help +Show invocation help and exit. +.PD +.SH "SEE ALSO" +.Sp +http://rubyforge.org/projects/ruby-debug/ +.SH AUTHOR +rdebug was written by Kent Siblev. This manual page was written by +Rocky Bernstein diff --git a/doc/.svn/text-base/ruby-debug.texi.svn-base b/doc/.svn/text-base/ruby-debug.texi.svn-base new file mode 100644 index 0000000..c50ae37 --- /dev/null +++ b/doc/.svn/text-base/ruby-debug.texi.svn-base @@ -0,0 +1,3982 @@ +\input texinfo @c -*-texinfo-*- +@setfilename ruby-debug.info + +@set DBG ruby-debug +@set ttrdebug @code{rdebug} +@set ttDBG @code{@value{DBG}} +@set Emacs @sc{gnu} Emacs + +@c Karl Berry informs me that this will add straight quotes in +@c typewriter text. +@c See the "Inserting Quote Characters" node in the Texinfo manual +@set txicodequoteundirected +@set txicodequotebacktick +@set RDEBUG_VERSION 0.10.4 + +@macro Example {} +@iftex +@cartouche +@end iftex +@smallexample +@end macro + +@macro EndExample {} +@iftex +@end cartouche +@end iftex +@end smallexample +@end macro + +@macro DBG {} +@value{DBG} +@end macro + +@macro ttDBG {} +@value{ttrdebug} +@end macro + +@c How to show optional variables. +@macro ovar{varname} +@r{[}@var{\varname\}@r{]} +@end macro + +@settitle ruby-debug +@setchapternewpage odd +@c %**end of header + +@include version.texi + +@finalout + +@c THIS MANUAL REQUIRES TEXINFO 4.0 OR LATER. + +@c This is a dir.info fragment to support semi-automated addition of +@c manuals to an info tree. +@dircategory Programming & development tools. +@direntry +* ruby-debug: (ruby-debug). Ruby Debugger +@end direntry + +@titlepage +@title Debugging with @code{ruby-debug} +@sp 1 +@subtitle @value{EDITION} Edition +@subtitle @value{UPDATED-MONTH} +@author Rocky Bernstein and Kent Sibilev +@page +@ifset WHERETO +@tex +{\parskip=0pt +\hfill (Send bugs and comments on ruby-debug to fill in...)\par +\hfill {\it Debugging with {\tt ruby-debug}\par +\hfill \TeX{}info \texinfoversion\par +} +@end tex +@end ifset +@end titlepage +@page + +@ifnottex +@node Top, Summary, (dir), (dir) +@top Debugging with ruby-debug + +This file describes ruby-debug, the Ruby Debugger, +version @value{RDEBUG_VERSION} + +This is the @value{EDITION} Edition, @value{UPDATED} +@c Copyright (C) 2007 ... + +@menu +* Summary:: Overview of Debugger with sample sessions +* Invocation:: Getting in and out +* Debugger Command Reference:: rdebug command reference +* Post-Mortem Debugging:: Debugging on an uncaught exception +* Debugger Module and Class:: ruby-debug's Debugger module and class + +Appendix +* Using from Subversion:: + +Indexes (nodes containing large menus) +* Class Module Index:: An item for Class, Module, and Methods. +* Command Index:: An item for each command name. +* General Index:: An item for each concept. +@end menu + +@end ifnottex + +@contents + +@node Summary +@chapter Summary of @code{ruby-debug} + +The purpose of a debugger such as @DBG{} is to allow you to see what is +going on ``inside'' a Ruby program while it executes. + +@ttDBG{} can do four main kinds of things (plus other things in support of +these) to help you catch bugs in the act: + +@itemize @bullet +@item +Start your script, specifying anything that might affect its behavior. + +@item +Make your script stop on specified conditions. + +@item +Examine what has happened, when your script has stopped. + +@item +Change things in your script, so you can experiment with correcting the +effects of one bug and go on to learn about another. +@end itemize + +Although you can use @value{ttrdebug} to invoke your Ruby programs via +a debugger at the outset, there are other ways to use and enter the +debugger. + +@menu +* First Sample Session:: A Simple Sample @code{rdebug} session +* Second Sample Session:: Second Session Delving a little deeper @code{rdebug} session +* Unit Testing Session:: Using the debugger in unit testing +* Debugger.start with a block:: Using the Debugger.start with a block +* Debugging Oddities:: How debugging Ruby may be different... +@end menu + +@node First Sample Session +@section The First Sample @code{rdebug} Session (@code{list}, @code{display}, @code{print}, and @code{quit}) + +You can use this manual at your leisure to read all about @value{ttDBG}. +However, a handful of commands are enough to get started using the +debugger. The following sections illustrates these commands. + +@iftex +In this sample session, we emphasize user input like this: @b{input}, +to make it easier to pick out from the surrounding output. +@end iftex + +Below is Ruby code to compute a triangle number of a given +length.@footnote{There are of course shorter ways to define @code{triangle} +such as: +@smallexample + def triangle(n) (n * (n+1)) / 2 end +@end smallexample +The code we use in this example and the next is more for pedagogical +purposes than how to write short Ruby code.} + + +@smallexample +$ @b{rdebug triangle.rb} +triangle.rb:4 def hanoi(n,a,b,c) +(rdb:1) @b{list} +[-1, 8] in ./triangle.rb + 1 #!/usr/bin/env ruby + 2 # Compute the n'th triangle number - the hard way + 3 # triangle(n) == (n * (n+1)) / 2 +=> 4 def triangle(n) + 5 tri = 0 + 6 0.upto(n) do |i| + 7 tri += i + 8 end +(rdb:1) @b{l} +[9, 18] in ./triangle.rb + 9 return tri + 10 end + 11 + 12 puts triangle(3) +(rdb:1) @b{list 1,100} +[1, 100] in ./triangle.rb + 1 #!/usr/bin/env ruby + 2 # Compute the n'th triangle number - the hard way + 3 # triangle(n) == (n * (n+1)) / 2 +=> 4 def triangle(n) + 5 tri = 0 + 6 0.upto(n) do |i| + 7 tri += i + 8 end + 9 return tri + 10 end + 11 + 12 puts triangle(3) +(rdb:1) +@end smallexample + +@noindent + +There are lots of command options, but we don't need them for now. See +@ref{rdebug command-line options} for a full list of command options. + +Position information consists of a filename and line number, +e.g.@: @code{triangle.rb:4}. We are currently stopped before the first +executable line of the program; this is line 4 of +@code{triangle.rb}. If you are used to less dynamic languages and have +used debuggers for more statically compiled languages like C, C++, or +Java, it may seem odd to be stopped before a function definition. But +in Ruby line 4 is executed, the name @code{triangle} (probably) does +not exist so issuing a method call of @code{triangle} will raise a +``method not found'' error. + +@DBG{}'s prompt is @code{(rdb:@emph{n})}. The @emph{n} is the thread +number. Here it is 1 which is usually the case for the main thread. If +the program has died and you are in post-mortem debugging, there is no +thread number. In this situation, the string @code{post-mortem} is +used in place of a thread number. If the program has terminated +normally, the string this position will be @code{ctrl}. The commands +which are available change depending on the program state. + +The first command, @code{list} (@pxref{List}), prints 10 lines +centered around the current line; the current line here is line 4 and +is marked by @code{=>}, so the range the debugger would like to show +is -1..8. However since there aren't 5 lines before the current line, +those additional lines---``lines'' -1 and 0---are dropped and we print +the remaining 8 lines. The @code{list} command can be abbreviated +with @code{l} which is what we use next. Notice that when we use this +a second time, we continue listing from the place we last left +off. The desired range of lines this time is lines 9 to 18; but since +the program ends as line 12, only the remaining 4 lines are shown. + +If you want to set how many lines to print by default rather than use +the initial number of lines, 10, use the @code{set listsize} command +(@pxref{Listsize}). To see the entire program in one shot, we gave an +explicit starting and ending line number. + +If you use a front-end to the debugger such as the Emacs interface, +@c (@pxref{GNU Emacs}) +you probably won't use @code{list} all that much. + +Now let us step through the program. + +@smallexample +(rdb:1) @b{step} +triangle.rb:12 +puts triangle(3) +(rdb:1) @b{@key{}} +triangle.rb:5 +tri = 0 +(rdb:1) @b{p tri} +nil +(rdb:1) @b{step} +triangle.rb:6 +0.upto(n) do |i| +(rdb:1) @b{p tri} +0 +@end smallexample + +The first @kbd{step} command (@pxref{Step}) runs the script one +executable unit. The second command we entered was just hitting the +return key; @ttDBG{} remembers the last command you entered was +@code{step}, so it runs that last command again. + +One way to print the values of variables uses @code{p}. (Of course, +there are of course lots of other ways too.). When we look at the +value of @code{tri} the first time, we see it is @code{nil}. Again we +are stopped @emph{before} the assignment on line 5, and this variable +hasn't been set previously. However after issuing another ``step'' +command we see that the value is 0 as expected. You could issue the +step and print comman in one shot: + +However if every time we stop we want to see the value of @code{tri} +to see how things are going stop, there is a better way by setting a +display expression (@pxref{DisplayCommands}). + +@smallexample +(rdb:1) display tri +1: tri = 0 +@end smallexample + +Now let us run the program until we return from the function. However +we'll want to see which lines get run. + +@smallexample +(rdb:1) @b{display i} +2: i = +(rdb:1) @b{set linetrace on} +line tracing is on. +(rdb:1) @b{finish} +Tracing(1):triangle.rb:7 tri += i +1: tri = 0 +2: i = 0 +Tracing(1):triangle.rb:7 tri += i +1: tri = 0 +2: i = 1 +Tracing(1):triangle.rb:7 tri += i +1: tri = 1 +2: i = 2 +Tracing(1):triangle.rb:7 tri += i +1: tri = 3 +2: i = 3 +Tracing(1):triangle.rb:9 return tri +1: tri = 6 +2: i = +(rdb:1) @b{quit} +Really quit? (y/n) y +@end smallexample + +So far, so good. A you can see from the above to get out of the +debugger, one can issue a @code{quit} command. (@code{q} and +@code{exit} are just as good. If you want to quit without being +prompted, suffix the command with an exclamation mark, e.g.\@code{q!}. + +@node Second Sample Session +@section Sample Session 2: Delving Deeper (@code{where}, @code{frame}, @code{restart}, @code{autoeval}, @code{break}, @code{ps}) + +In this section we'll introduce breakpoints, the call stack and +restarting. So far we've been doing pretty good in that we've not +encountered a bug to fix. Let's try another simple example. Okay +here's the program. + +Below we will debug a simple Ruby program to solve the classic Towers +of Hanoi puzzle. It is augmented by the bane of programming: some +command-parameter processing with error checking. + +@smallexample +$ @b{rdebug hanoi.rb} +hanoi.rb:3 def hanoi(n,a,b,c) +(rdb:1) @b{list 1,100} +[1, 100] in ./hanoi.rb + 1 #!/usr/bin/ruby + 2 +=> 3 def hanoi(n,a,b,c) + 4 if n-1 > 0 + 5 hanoi(n-1, a, c, b) + 6 end + 7 puts "Move disk %s to %s" % [a, b] + 8 if n-1 > 0 + 9 hanoi(n-1, c, b, a) + 10 end + 11 end + 12 + 13 i_args=ARGV.length + 14 if i_args > 1 + 15 puts "*** Need number of disks or no parameter" + 16 exit 1 + 17 end + 18 + 19 n=3 + 20 + 21 if i_args > 0 + 22 begin + 23 n = ARGV[0].to_i + 24 rescue ValueError, msg: + 25 print "** Expecting an integer, got: %s" % ARGV[0].to_s + 26 exit 2 + 27 end + 28 end + 29 + 30 if n < 1 or n > 100 + 31 puts "*** number of disks should be between 1 and 100" + 32 exit 2 + 33 end + 34 + 35 hanoi(n, :a, :b, :c) +(rdb:1) +@end smallexample + +Recall in the first section I said that before the @code{def} is run +the method it names is undefined. Let's check that out. First let's +see what private methods we can call before running @code{def hanoi} + +@smallexample +(rdb:1) @b{set autoeval on} +autoeval is on. +(rdb:1) @b{private_methods} +["select", "URI", "local_variables", "lambda", "chomp", ... +@end smallexample + +The @code{set autoeval} (@pxref{Autoeval}) command causes any commands +that are not normally understood to be debugger commands to get +evaluated as though they were Ruby commands. I use this a lot, so I +set this by putting it the command file @code{.rdebugrc}, +@pxref{Command Files}, that gets read when @code{ruby-debug} starts. + +As showing the list output of @code{private_methods}, I find this kind +of list unwieldy. What you are supposed to notice here is that +method @code{hanoi} is not in this list. When you ask +@code{ruby-debug} for a list of method names via @code{method +instance}, it doesn't show output in this way; @code{ruby-debug} can +sort and put into columns lists like this using the print command, @code{ps}. + + +@smallexample +(rdb:1) @b{ps private_methods} +Array exit! puts warn +Float fail raise y +Integer fork rand +Rational format readline +String gem_original_require readlines +URI getc remove_instance_variable +` gets scan +abort global_variables select +active_gem_with_options gsub set_trace_func +at_exit gsub! singleton_method_added +autoload initialize singleton_method_removed +autoload? initialize_copy singleton_method_undefined +binding iterator? sleep +block_given? lambda split +callcc load sprintf +caller local_variables srand +catch location_of_caller sub +chomp loop sub! +chomp! method_missing syscall +chop open system +chop! p test +dbg_print pp throw +dbg_puts print timeout +eval printf trace_var +exec proc trap +exit putc untrace_var +@end smallexample + +Now let's see what happens after stepping + +@smallexample +(rdb:1) @b{private.methods.member?("hanoi")} +false +(rdb:1) @b{step} +hanoi.rb:13 +i_args=ARGV.length +(rdb:1) @b{private_methods.member?("hanoi")} +true +(rdb:1) +@end smallexample + +Okay, now where were we? + +@smallexample +(rdb:1) @b{list} +[8, 17] in ./hanoi.rb + 8 if n-1 > 0 + 9 hanoi(n-1, c, b, a) + 10 end + 11 end + 12 +=> 13 i_args=ARGV.length + 14 if i_args > 1 + 15 puts "*** Need number of disks or no parameter" + 16 exit 1 + 17 end +(rdb:1) @b{ARGV} +[] +@end smallexample + +Ooops. We forgot to specify any parameters to this program. Let's try +again. We can use the @code{restart} command here. + +@smallexample +(rdb:1) @b{restart 3} +Re exec'ing: + /usr/bin/rdebug hanoi.rb 3 +hanoi.rb:3 +def hanoi(n,a,b,c) +(rdb:1) @b{break 4} +Breakpoint 1 file hanoi.rb, line 4 +(rdb:1) @b{continue} +Breakpoint 1 at hanoi.rb:4 +./hanoi.rb:4 if n-1 > 0 +(rdb:1) @b{display n} +1: n = 3 +(rdb:1) @b{display a} +2: a = a +(rdb:1) @b{undisplay 2} +(rdb:1) @b{display a.inspect} +3: a.inspect = :a +(rdb:1) @b{display b.inspect} +4: b.inspect = :b +(rdb:1) @b{continue} +Breakpoint 1 at hanoi.rb:4 +./hanoi.rb:4 +if n-1 > 0 +1: n = 2 +3: a.inspect = :a +4: b.inspect = :c +(rdb:1) @b{c} +Breakpoint 1 at hanoi.rb:4 +./hanoi.rb:4 +if n-1 > 0 +1: n = 1 +3: a.inspect = :a +4: b.inspect = :b +(rdb:1) @b{where} +--> #0 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:4 + #1 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5 + #2 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5 + #3 at line hanoi.rb:35 +(rdb:1) +@end smallexample + +In the above we added a new command, @code{break} +(@pxref{Breakpoints}) which indicates to go into the debugger just +before that line of code is run. And @code{continue} resumes +execution. Notice the difference between @code{display a} and +@code{display a.inspect}. An implied string conversion is performed on +the expression after it is evaluated. To remove a display expression +we used @code{undisplay} is used. If we give a display number, just +that display expression is removed. + +Above we also used a new command @code{where} (@pxref{Backtrace} to +show the call stack. In the above situation, starting from the bottom +line we see we called the hanoi from line 35 of the file +@code{hanoi.rb} and the hanoi method called itself two more times at +line 5. + +In the call stack we show the file line position in the same format +when we stop at a line. Also we see the names of the parameters and +the types that those parameters @emph{currently} have. It's possible +that when the program was called the parameter had a different type, +since the types of variables can change dynamically. You alter the +style of what to show in the trace (@pxref{Callstyle}). + +Let's explore a little more. Now were were we? + +@smallexample +(rdb:1) @b{list} + 1 #!/usr/bin/ruby + 2 + 3 def hanoi(n,a,b,c) +=> 4 if n-1 > 0 + 5 hanoi(n-1, a, c, b) + 6 end + 7 puts "Move disk %s to %s" % [a, b] + 8 if n-1 > 0 +(rdb:1) @b{undisplay} +Clear all expressions? (y/n) @b{y} +(rdb:1) @b{i_args} +NameError Exception: undefined local variable or method `i_args' for main:Object +(rdb:1) @b{frame -1} +#3 at line hanoi.rb:35 +(rdb:1) @b{i_args} +1 +(rdb:1) @b{p n} +3 +(rdb:1) @b{down 2} +#2 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5 +(rdb:1) @b{p n} +2 +@end smallexample + +Notice in the above to get the value of variable @code{n}, I have to +use a print command like @code{p n}; If I entered just @code{n}, that +would be taken to mean the debugger command ``next''. In the current +scope, variable @code{i_args} is not defined. However I can change to +the top-most frame by using the @code{frame} command. Just as with +arrays, -1 means the last one. Alternatively using frame number 3 +would have been the same thing; so would issuing @code{up 3}. + +Note that in the outside frame 3, the value of @code{i_args} can be +shown. Also note that the value of variable @code{n} is different. + +@node Unit Testing Session +@section Using the debugger in unit testing (@code{ruby-debug/debugger}, @code{Debugger.start}) + +In the previous sessions we've been calling the debugger right at the +outset. I confess that this mode of operation is usually not how I use +the debugger. + +There are a number of situations where calling the debugger at the outset is +impractical for a couple of reasons. + +@enumerate +@item +The debugger just doesn't work when run at the outset. By necessity +any debugging changes to the behavior or the program in slight and +subtle ways, and sometimes this can hinder finding the bugs. +@item +There's a lot of code which that needs to get run before the part you +want to inspect. Running this code takes time and you don't the +overhead of the debugger in this first part. +@end enumerate + +In this section we'll delve show how to enter the code in the middle +of your program, while delving more into the debugger operation. + +In this section we will also use unit testing. Using unit tests will +greatly reduce the amount of debugging needed while at the same time +increase the quality of your program. + +What we'll do is take the @code{triangle} code from the first session +and write a unit test for that. In a sense we did write a mini-test +for the program which was basically the last line where we printed the +value of triangle(3). This test however wasn't automated: the +implication is that someone would look at the output and verify that +what was printed is what was expected. + +And before we can turn that into something that can be +@code{required}, we probably want to remove that output. However I +like to keep in that line so that when I look at the file, I have an +example of how to run it. Therefore we will conditionally run this +line if that file is invoked directly, but skip it if it is +not.@footnote{@code{rdebug} resets @code{$0} to try to make things +like this work.} +@smallexample + if __FILE__ == $0 + puts triangle(3) + end +@end smallexample + +Let's call this file @code{tri2.rb}. + +Okay, we're now ready to write our unit test. We'll use +@code{"test/unit"} which comes with the standard Ruby distribution. +Here's the test code: + +@smallexample + #!/usr/bin/env ruby + require 'test/unit' + require 'tri2.rb' + + class TestTri < Test::Unit::TestCase + def test_basic + solutions = [] + 0.upto(5) do |i| + solutions << triangle(i) + end + assert_equal([0, 1, 3, 6, 10, 15], solutions, + 'Testing the first 5 triangle numbers') + end + end +@end smallexample + +If you run it will work. However if you run @code{rdebug} initially, +you will not get into the test, because @code{test/unit} wants to be +the main program. So here is a situation where one may need to modify +the program to add an explicit @emph{entry} into the +debugger.@footnote{For some versions of rake and @code{rdebug} you can +in fact set a breakpoint after running @code{rdebug} +initially. Personally though I find it much simpler and more reliable +to modify the code as shown here.} + +One way to do this is to add the following before the place you want +to stop: +@smallexample + require 'rubygems' + require 'ruby-debug/debugger' +@end smallexample +The line @code{require "rubygems"} is needed if @code{ruby-debug} is +installed as a Ruby gem. + +Let's add this code just after entering @code{test_basic}: +@smallexample + ... + def test_basic + @b{require "rubygems"} + @b{require "ruby-debug/debugger"} + solutions = [] + ... +@end smallexample + +Now we run the program.. +@smallexample + $ @b{ruby test-tri.rb} + Loaded suite test-tri + Started + test-tri.rb:9 + solutions = [] + (rdb:1) +@end smallexample +and we see that we are stopped at line 9 just before the +initialization of the list @code{solutions}. + +Now let's see where we are... + +@smallexample +(rdb:1) @b{where} +--> #0 TestTri.test_basic at line /home/rocky/ruby/test-tri.rb:9 +(rdb:1) +@end smallexample + +Something seems wrong here; @code{TestTri.test_basic} indicates that +we are in class @code{TestTri} in method @code{test_basic}. However we +don't see the call to this like we did in the last example when we +used the @code{where} command. This is because the debugger really +didn't spring into existence until after we already entered that +method, and Ruby doesn't keep call stack information around in a +way that will give the information we show when running @code{where}. + +If we want call stack information, we have to turn call-stack tracking +on @emph{beforehand}. This is done by adding @code{Debugger.start}. + +Here's what our test program looks like so after we modify it to start +tracking calls from the outset + +@smallexample +#!/usr/bin/env ruby +require 'test/unit' +require 'tri2.rb' +require 'rubygems' +@b{Debugger.start} + +class TestTri < Test::Unit::TestCase + def test_basic + @b{debugger} + solutions = [] + 0.upto(5) do |i| + solutions << triangle(i) + end + assert_equal([0, 1, 3, 6, 10, 15], solutions, + "Testing the first 5 triangle numbers") + end +end +@end smallexample + +Now when we run this: +@smallexample +$ @b{ruby test-tri2.rb} +Loaded suite test-tri2 +Started +test-tri2.rb:11 +solutions = [] +(rdb:1) @b{where} +--> #0 TestTri.test_basic at line test-tri2.rb:11 + #1 Kernel.__send__(result#Test::Unit::TestResult) + at line /usr/lib/ruby/1.8/test/unit/testcase.rb:70 + #2 Test::Unit::TestCase.run(result#Test::Unit::TestResult) + at line /usr/lib/ruby/1.8/test/unit/testcase.rb:70 +... + #11 Test::Unit::AutoRunner.run + at line /usr/lib/ruby/1.8/test/unit/autorunner.rb:200 + #12 Test::Unit::AutoRunner.run(force_standalone#FalseClass, ... + at line /usr/lib/ruby/1.8/test/unit/autorunner.rb:13 + #13 at line /usr/lib/ruby/1.8/test/unit.rb:285 +(rdb:1) +@end smallexample + +Much better. But again let me emphasize that the parameter types are +those of the corresponding variables that @emph{currently} exist, and +this might have changed since the time when the call was made. Even so +and even though we only have @emph{types} listed, it's a pretty good +bet that when @code{Test::Unit} was first called, shown above as frame +12, that the values of its two parameters were @code{false} and +@code{nil}. + +@node Debugger.start with a block +@section Using the @code{Debugger.start} with a block + +We saw that @code{Debugger.start()} and @code{Debugger.stop()} allow +fine-grain control over where the debugger tracking should occur. + +Rather than use an explicit @code{stop()}, you can also pass a block +to the @code{start()} method. This causes @code{start()} to run and +then @code{yield} to that block. When the block is finished, +@code{stop()} is run. In other words, this wraps a +@code{Debugger.start()} and @code{Debugger.stop()} around the block of +code. But it also has a side benefit of ensuring that in the presence +of an uncaught exception @code{stop} is run, without having to +explicitly use @code{begin} ... @code{ensure Debugger.stop() end}. + +For example, in Ruby Rails you might want to debug code in one of the +controllers without causing any slowdown to any other code. And +this can be done by wrapping the controller in a @code{start()} with a +block; when the method wrapped this way finishes the debugger is +turned off, and the application proceeds at regular speed. + +Of course, inside the block you will probably want to enter the +debugger using @code{Debugger.debugger()}, otherwise there would +little point in using the @code{start}. For example, you can do this +in @code{irb}: + +@smallexample +$ @b{irb} +irb(main):001:0> @b{require 'rubygems'; require 'ruby-debug'} +=> true +irb(main):002:0> @b{def foo} +irb(main):003:1> @b{x=1} +irb(main):004:1> @b{puts 'foo'} +irb(main):005:1> @b{end} +=> nil +irb(main):006:0> @b{Debugger.start@{debugger; foo@}} +(irb):6 +(rdb:1) @b{s} +(irb):3 +(rdb:1) @b{p x} +nil +(rdb:1) @b{s} +(irb):4 +(rdb:1) @b{p x} +1 +(rdb:1) @b{s} +foo +=> true +irb(main):007:0> +@end smallexample + +There is a counter inside of @code{Debugger.start} method to make sure +that this works when another @code{Debugger.start} method is called +inside of outer one. However if you are stopped inside the debugger, +issuing another @code{debugger} call will not have any effect even if +it is nested inside another @code{Debugger.start}. + +@node Debugging Oddities +@section How debugging Ruby may be different than debugging other Languages + +If you are used to debugging in other languages like C, C++, Perl, +Java or even Bash@footnote{this is just an excuse to put in a +shameless plug for my bash debugger @url{http://bashdb.sf.net}}, there +may be a number of things that seem or feel a little bit different and +may confuse you. A number of these things aren't oddities of the +debugger per see, so much as a difference in how Ruby works compared to +those other languages. Because Ruby works a little differently from +those other languages, writing a debugger has to also be a little +different as well if it is to be useful. + +In this respect, using the debugger may help you understand Ruby +better. + +We've already seen two examples of such differences. One difference is +the fact that we stop on method definitions or @code{def}'s and that's +because these are in fact executable statements. In other compiled +languages this would not happen because that's already been done when +you compile the program (or in Perl when it scans in the program). The +other difference we saw was in our inability to show call stack parameter +types without having made arrangements for the debugger to track +this. In other languages call stack information is usually available +without asking assistance of the debugger.@footnote{However in C, and +C++ generally you have to ask the compiler to add such information.} + +In this section we'll consider some other things that might throw +off new users to Ruby who are familiar with other languages and +debugging in them. + +@menu +* Stack Shows Scope Nesting:: +* More Frequent Evaluations per Line:: +* Bouncing Around in Blocks (e.g. Iterators):: +* No Parameter Values in a Call Stack:: +* Lines You Can Stop At:: +@end menu + +@node Stack Shows Scope Nesting +@subsection Stack Shows Scope Nesting +In a backtrace, you will find more stack frames than you might in say +C. + +Consider another way to write the triangle program of @pxref{First +Sample Session}. + +@smallexample + 1 #!/usr/bin/env ruby + 2 def triangle(n) + 3 (0..n).inject do |sum, i| + 4 sum +=i + 5 end + 6 end + 7 puts triangle(3) +@end smallexample + +Let's stop inside the @code{inject} block: + +@smallexample +$ @b{rdebug tri3.rb} +(rdb:1) @b{c 4} +tri3.rb:4 +sum +=i +(rdb:1) @b{where} +--> #0 Range.triangle at line tri3.rb:4 + #1 Enumerable.inject at line tri3.rb:3 + #2 Object.triangle(n#Fixnum) at line tri3.rb:3 + #3 at line tri3.rb:7 +(rdb:1) +@end smallexample +Because a new scope was entered, it appears as a stack frame. Probably +``scope'' frame would be a more appropriate name. + +@node More Frequent Evaluations per Line +@subsection More Frequent Evaluations per Line +Consider this simple program to compute the Greatest Common Divisor of +two numbers: +@smallexample + 1 #!/usr/bin/env ruby + 2 # GCD. We assume positive numbers + 3 + 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end + 9 +10 return nil if a <= 0 +11 +12 if a == 1 or b-a == 0 +13 return a +14 end +15 return gcd(b-a, a) +16 end +17 +18 a, b = ARGV[0..1].map @{|arg| arg.to_i@} +19 puts "The GCD of %d and %d is %d" % [a, b, gcd(a, b)] +@end smallexample + +Now let's try tracing a portion of the program to see what we get. +@smallexample +$ @b{rdebug gcd.rb 3 5} +gcd.rb:4 +def gcd(a, b) +(rdb:1) @b{step} +gcd.rb:18 +a, b = ARGV[0..1].map @{|arg| arg.to_i@} +(rdb:1) @b{step} +gcd.rb:18 +a, b = ARGV[0..1].map @{|arg| arg.to_i@} +(rdb:1) @b{step} +gcd.rb:18 +a, b = ARGV[0..1].map @{|arg| arg.to_i@} +(rdb:1) @b{step} +(rdb:1) @b{break Object.gcd} +Breakpoint 1 at Object::gcd +(rdb:1) @b{continue} +Breakpoint 1 at Object:gcd +gcd.rb:4 +def gcd(a, b) +(rdb:1) @b{set linetrace on} +line tracing is on. +(rdb:1) @b{continue} +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Breakpoint 1 at Object:gcd +gcd.rb:4 +def gcd(a, b) +(rdb:1) +@end smallexample + +The thing to note here is that we see lots of lines duplicated. For +example, the first line: +@smallexample +Tracing(1):gcd.rb:18 a, b = ARGV[0..1].map @{|arg| arg.to_i@} +@end smallexample +appears three times. If we were to break this line into the equivalent +multi-line expression: +@smallexample +a, b = ARGV[0..1].map do |arg| + arg.to_i +end +@end smallexample +we would find one stop at the first line before running @code{map} and +two listings of @code{arg.to_i}, once for each value of arg which here +is 0 and then 1. Perhaps this is is not surprising because we have a +loop here which gets run in this situation 3 times. A similar command +@code{next}, can also be used to skip over loops and method +calls. + +But what about all the duplicated @code{if} statements in @code{gcd}? +Each one is listed twice whether or not we put the @code{if} at the +beginning or the end. You will find this to be the case for any +conditional statement such as @code{until} or @code{while}. + +Each statement appears twice because we stop once before the +expression is evaluated and once after the expression is evaluated but +before the if statement takes hold. There is a bug in Ruby up to +version 1.8.6 in that we stop a second time before the evaluation, so +examining values that may have changed during the expression +evaluation doesn't work in these versions. + +If you are issuing a @code{step} command one at a time, the repetitive +nature can be little cumbersome if not annoying. So @value{DBG} offers +a variant called @code{step+} which forces a new line on every +step. Let's try that. +@smallexample +(rdb:1) @b{R} +Re exec'ing: + /usr/bin/rdebug gcd.rb 3 5 +gcd.rb:4 +def gcd(a, b) +(rdb:1) @b{step+} +gcd.rb:18 +a, b = ARGV[0..1].map @{|arg| arg.to_i@} +(rdb:1) @b{step+} +gcd.rb:19 +puts "The GCD of %d and %d is %d" % [a, b, gcd(a, b)] +(rdb:1) @b{break Object.gcd} +Breakpoint 1 at Object:gcd +(rdb:1) @b{c} +Breakpoint 1 at Object:gcd +gcd.rb:4 +def gcd(a, b) +(rdb:1) @b{set linetrace+} +line tracing style is different consecutive lines. +(rdb:1) @b{set linetrace on} +line tracing is on. +(rdb:1) @b{c} +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Breakpoint 1 at Object:gcd +gcd.rb:4 +def gcd(a, b) +@end smallexample + +If you want @code{step+} to be the default behavior when stepping, +issue the command @code{set forcestep on}, (@pxref{Forcestep}). I +generally put this in my start-up file @code{.rdebugrc}. + +Similar to the difference between @code{step+} and @code{step} is +@code{set linetrace+}. This removes duplicate consecutive line tracing. + +One last thing to note above is the use of a method name to set a +breakpoint position, rather than a file and line number. Because +method @code{gcd} is in the outermost scope, we use @code{Object} as the +class name. + +@node Bouncing Around in Blocks (e.g. Iterators) +@subsection Bouncing Around in Blocks (e.g.@: Iterators) + +When debugging languages with coroutines like Python and Ruby, a +method call may not necessarily go to the first statement after the +method header. It's possible the call will continue after a +@code{yield} statement from a prior call. + +@smallexample + 1 #!/usr/bin/env ruby + 2 # Enumerator for primes + 3 class SievePrime + 4 @@@@odd_primes = [] + 5 def self.next_prime(&block) + 6 candidate = 2 + 7 yield candidate + 8 not_prime = false + 9 candidate += 1 +10 while true do +11 @@@@odd_primes.each do |p| +12 not_prime = (0 == (candidate % p)) +13 break if not_prime +14 end +15 unless not_prime +16 @@@@odd_primes << candidate +17 yield candidate +18 end +19 candidate += 2 +20 end +21 end +22 end +23 SievePrime.next_prime do |prime| +24 puts prime +25 break if prime > 10 +26 end +@end smallexample + +@smallexample +$ @b{rdebug primes.rb} +primes.rb:3 +class SievePrime +(rdb:1) @b{set linetrace on} +line tracing is on. +(rdb:1) @b{step 10} +Tracing(1):primes.rb:4 @@odd_primes = [] +Tracing(1):primes.rb:5 def self.next_prime(&block) +Tracing(1):primes.rb:23 SievePrime.next_prime do |prime| +Tracing(1):primes.rb:6 candidate = 2 +Tracing(1):primes.rb:7 yield candidate +Tracing(1):primes.rb:24 puts prime +2 +Tracing(1):primes.rb:25 break if prime > 10 +Tracing(1):primes.rb:25 break if prime > 10 +Tracing(1):primes.rb:8 not_prime = false +Tracing(1):primes.rb:9 candidate += 1 +primes.rb:9 +candidate += 1 +(rdb:1) +@end smallexample + +The loop between lines 23--26 gets interleaved between those of +@code{Sieve::next_prime}, lines 6--19 above. + +A similar kind of thing can occur in debugging programs with many threads. + +@node No Parameter Values in a Call Stack +@subsection No Parameter Values in a Call Stack +In traditional debuggers in a call stack you can generally see the +names of the parameters and the values that were passed in. + +Ruby is a very dynamic language and it tries to be efficient within +the confines of the language definition. Values generally aren't taken +out of a variable or expression and pushed onto a stack. Instead a new +scope created and the parameters are given initial values. Parameter +passing is by @emph{reference}, not by value as it is say Algol, C, or +Perl. During the execution of a method, parameter values can +change---and often do. In fact even the @emph{class} of the object can +change. + +So at present, the name of the parameter shown. The call-style setting +@pxref{Callstyle} can be used to set whether the name is shown or the +name and the @emph{current} class of the object. + +It has been contemplated that a style might be added which saves on +call shorter ``scalar'' types of values and the class name. + +@node Lines You Can Stop At +@subsection Lines You Can Stop At +As with the duplicate stops per control (e.g.@: @code{if} statement), +until tools like debuggers get more traction among core ruby +developers there are going to be weirdness. Here we describe the +stopping locations which effects the breakpoint line numbers you can +stop at. + +Consider the following little Ruby program. + +@smallexample +'Yes it does' =~ / +(Yes) \s+ +it \s+ +does +/ix +puts $1 +@end smallexample + +The stopping points that Ruby records are the last two lines, lines 5 +and 6. If you run @code{ruby -rtracer} on this file you'll see that +this is so: + +@smallexample +$ ruby -rtracer lines.rb +#0:lines.rb:5::-: /ix +#0:lines.rb:6::-: puts $1 +#0:lines.rb:6:Kernel:>: puts $1 +#0:lines.rb:6:IO:>: puts $1 +Yes#0:lines.rb:6:IO:<: puts $1 +#0:lines.rb:6:IO:>: puts $1 + +#0:lines.rb:6:IO:<: puts $1 +#0:lines.rb:6:Kernel:<: puts $1 +@end smallexample + +Inside @code{ruby-debug} you an get a list of stoppable lines for a +file using the @code{info file} command with the attribute +@code{breakpoints}. + +@ifset FINISHED +To be continued... + +@itemize @bullet +@item more complex example with objects, pretty printing and irb. +@item line tracing and non-interactive tracing. +@item mixing in Debugger.debug with rdebug +@item post-mortem debugging and setting up for that +@item threading? +@item references to videos +@end itemize +@end ifset + +@node Invocation +@chapter Getting in and out + +@menu +* Starting the debugger:: How to enter the debugger +* Command Files:: Command files +* Quitting the debugger:: How to leave the debugger (quit, kill) +* Calling from Program:: Calling the debugger from inside your program +@end menu + +It is also possible to enter the debugger when you have an uncaught +exception. See See also @ref{Post-Mortem Debugging}. + +@node Starting the debugger +@section Starting the debugger + +Although one can enter @DBG{} via Emacs (described in a later section) +and possibly others interfaces, probably the most familiar thing to do +is invoke the debugger from a command line. + +A wrapper shell script called @code{rdebug} basically @code{require}'s +the gem package @code{ruby-debug} and then loads @code{rdebug}. + +@smallexample +rdebug [rdebug-options] [--] @var{ruby-script} @var{ruby-script-arguments...} +@end smallexample + +If you don't need to pass dash options to your program which might get +confused with the debugger options, then you don't need to add the +@option{--}. + +To get a brief list of options and descriptions, use the @code{--help} +option. + +@smallexample +$ @b{rdebug --help} +rdebug @value{RDEBUG_VERSION} +Usage: rdebug [options] -- + +Options: + -A, --annotate LEVEL Set annotation level + -c, --client Connect to remote debugger + --cport PORT Port used for control commands + -d, --debug Set $DEBUG=true + --emacs Activates full Emacs support + --emacs-basic Activates basic Emacs mode + -h, --host HOST Host name used for remote debugging + -I, --include PATH Add PATH to $LOAD_PATH + --keep-frame-binding Keep frame bindings + -m, --post-mortem Activate post-mortem mode + --no-control Do not automatically start control thread + --no-quit Do not quit when script finishes + --no-rewrite-program Do not set $0 to the program being debugged + --no-stop Do not stop when script is loaded + -p, --port PORT Port used for remote debugging + -r, --require SCRIPT Require the library, before executing your script + --script FILE Name of the script file to run + -s, --server Listen for remote connections + -w, --wait Wait for a client connection, implies -s option + -x, --trace Turn on line tracing + +Common options: + --verbose Turn on verbose mode + --help Show this message + --version Print the version + -v Print version number, then turn on verbose mode +@end smallexample + +Options for the @code{rdebug} are shown in the following list. + +@menu +* rdebug command-line options:: Options you can pass to rdebug +* rdebug default options:: How to Set Default Command-Line Options +@end menu + +@node rdebug command-line options +@subsection Options you can pass to rdebug + +You can run @DBG{} in various alternative modes---for example, as a +program that interacts directly with the program in the same process +on the same computer or via a socket to another process possibly on a +different computer. + +Many options appear as a long option name, such as @option{--help}, and +a short one letter option name, such as @option{-h}. A double dash +(@option{--} is used to separate options which go to @code{rdebug} from +options that are intended to go to your Ruby script. Options (if any) +to @code{rdebug} should come first. If there is no possibility of the +Ruby script to be debugged getting confused with @code{rdebug}'s +option the double dash can be omitted. + +@table @code +@item --help +@cindex @option{-h} +@cindex @option{--help} +This option causes @ttDBG{} to print some basic help and exit. + +@item -v | --version +@cindex @option{-v} +This option causes @ttDBG{} to print its version number and exit. + +@item -A | --annotate @var{level} +@cindex @option{-A} +@cindex @option{--annotation} @var{level} +Set gdb-style annotation @var{level}, a number. Additional information is output +automatically when program state is changed. This can be used by +front-ends such as GNU Emacs to post this updated information without +having to poll for it. +@item -c | --client +@cindex @option{-c} +@cindex @option{--client} +Connect to remote debugger. The remote debugger should have been set +up previously our you will get a connection error and @code{rdebug} +will terminate. + +@item --cport @var{port} +@cindex @option{--cport} @var{port} +Port used for control commands. + +@item --debug +@cindex @option{--debug} +Set @code{$DEBUG} to @code{true}. This option is compatible with +Ruby's. + +@item --emacs +Activates GNU Emacs mode. +@c @pxref{GNU Emacs}. +Debugger output is tagged in such a way to allow GNU Emacs to track +where you are in the code. + +@item --emacs-basic +Activates full GNU Emacs mode. +@c (@pxref{GNU Emacs}). +This is the equivalent of setting the options @option{--emacs-basic}, +@code{annotate=3}, @option{--no-stop}, @option{-no-control} and +@option{--post-mortem}. + +@item -h | --host @var{host-address} +Connect host address for remote debugging. + +@item -I --include @var{PATH} +@cindex @option{-I} @var{PATH} +@cindex @option{--include} @var{PATH} +Add @var{PATH} to @code{$LOAD_PATH} + +@item --keep-frame-binding +@cindex @option{--keep-frame-binding} +Bindings are used to set the proper environment in evaluating +expression inside the debugger. Under normal circumstances, I don't +believe most people will ever need this option. + +By default, the debugger doesn't create binding object for each frame +when the frame is created, i.e. when a call is performed. Creating a +binding is an expensive operation and has been a major source of +performance problems. + +Instead, the debugger creates a binding when there is a need to +evaluate expressions. The artificial binding that is created might be +different from the real one. In particular, in performing constant +and module name resolution. + +However it's still possible to restore the old, slower behavior by +using this option or by setting @code{Debugger.keep_frame_binding = +true}. There are two possibilities for which you might want to use +this option. + +First, if you think there's a bug in the evaluation of variables, you +might want to set this to see if this corrects things. + +Second, since the internal structures that are used here @code{FRAME} +and @code{SCOPE} are not part of the Ruby specification, it is +possible they can change with newer releases; so here this option this +may offer a remedy. (But you'll probably also have to hack the C code +since it's likely under this scenario that ruby-debug will no longer +compile.) In fact, in Ruby 1.9 these structures have changed and that +is partly why this debugger doesn't work on Ruby 1.9. + +@item -m | --post-mortem +@cindex @option{-m} +@cindex @option{--post-mortem} +If your program raises an exception that isn't caught you can enter +the debugger for inspection of what went wrong. You may also want to +use this option in conjunction with @option{--no-stop}. See also +@ref{Post-Mortem Debugging}. + +@item --no-control +@cindex @option{--no-control} +Do not automatically start control thread. + +@item --no-quit +@cindex @option{--no-quit} +Restart the debugger when your program terminates normally. + +@item --no-rewrite-program +@cindex @option{--no-rewrite-program} +Normally @code{rdebug} will reset the program name @code{$0} from its +name to the debugged program, and set the its name in variable +@code{$RDEBUG_0}. In the unlikely even you don't want this use this option. + +@item --no-stop +@cindex @option{--no-stop} +Normally the @code{rdebug} stops before executing the first +statement. If instead you want it to start running initially and will +perhaps break it later in the running, use this options. + +@item -p | --port @var{port} +@cindex @option{-p} @var{port} +@cindex @option{--port} @var{port} +Port used for remote debugging. + +@item -r | --require @var{library} +@cindex @option{-r} +@cindex @option{--require} +Require the library, before executing your script. However if the +library happened to be @code{debug}, we'll just ignore the require +(since we're already a debugger). This option is compatible with Ruby's. + +@item --script @var{file} +@cindex @option{--script} +Require the library, before executing your script. However if the +library hap-pend to be @code{debug}, we'll just ignore the require +(since we're already a debugger). This option is compatible with Ruby's. + +@item -s | --server +@cindex @option{-s} +@cindex @option{--server} +Debug the program but listen for remote connections on the default +port or port set up via the @option{--port} option. See also @option{--wait}. + +@item -w | --wait +@cindex @option{-w} +@cindex @option{--wait} +Debug the program but stop waiting for a client connection first. This +option automatically sets @option{--server} option. + +@item -x | --trace +@cindex @option{-x} +@cindex @option{--trace} +Turn on line tracing. Running @command{rdebug --trace @emph{rubyscript.rb}} +is much like running: @command{ruby -rtracer @emph{rubyscript.rb}} + +If all you want to do however is get a linetrace, @code{tracer}, not +@code{rdebug}, may be faster: +@smallexample +$ @b{time ruby -rtracer gcd.rb 34 21 > /dev/null} + +real 0m0.266s +user 0m0.008s +sys 0m0.000s +$ @b{time rdebug --trace gcd.rb 34 21 > /dev/null} + +real 0m0.875s +user 0m0.448s +sys 0m0.056s +$ +@end smallexample + +@end table + +@node rdebug default options +@subsection How to Set Default Command-Line Options + +@DBG{} has many command-line options; it seems that some people want +to set them differently from the our defaults. For example, some +people may want @option{--no-quit --no-control} to be the default +behavior. One could write a wrapper script or set a shell alias to +handle this. @DBG{} has another way to do this as well. Before +processing command options if the file @code{$HOME/.rdboptrc} is found +it is loaded. If you want to set the defaults in some other way, you +can put Ruby code here and set variable @code{options} which is an +OpenStruct. For example here's how you'd set @option{-no-quit} and +change the default control port to 5000. + +@smallexample +# This file contains how you want the default options to ruby-debug +# to be set. Any Ruby code can be put here. +# +# debugger # Uncomment if you want to debug rdebug! +options.control = false +options.port = 5000 +puts "rocky's rdboptrc run" +@end smallexample + +Here are the default values in @code{options} +@smallexample +# +@end smallexample + + +@node Command Files +@section Command files + +@cindex command files +A command file for @DBG{} is a file of lines that are @DBG{} +commands. Comments (lines starting with @kbd{#}) may also be included. +An empty line in a command file does nothing; it does not mean to repeat +the last command, as it would from the terminal. + +@cindex init file +@cindex @file{.rdebugrc} +When you start @value{DBG}, it automatically executes commands from its +@dfn{init files}, normally called @file{.rdebugrc}. + +On some configurations of @value{DBG}, the init file may be known by a +different name. In particular on MS-Windows (but not cygwin) +@file{rdebug.ini} is used. + +During startup, @DBG{} does the following: + +@enumerate +@item +Processes command line options and operands. + +@item +Reads the init file in your current directory, if any, and failing +that the home directory. The home directory is the directory named in +the @code{HOME} or @code{HOMEPATH} environment variable. + +Thus, you can have more than one init file, one generic in your home +directory, and another, specific to the program you are debugging, in +the directory where you invoke @DBG{}. + +@item +Reads command files specified by the @samp{--script} option. +@end enumerate + +You can also request the execution of a command file with the +@code{source} command, @pxref{Source}. + +@node Quitting the debugger +@section Quitting the debugger + +@cindex interrupt +An interrupt (often @kbd{C-c}) does not exit from @value{DBG}, but +rather terminates the action of any @DBG command that is in +progress and returns to @value{DBG} command level. Inside a debugger +command interpreter, use @code{quit} command (@pxref{Control, ,Quitting +the debugger}). + +There way to terminate the debugger is to use the @code{kill} +command. This does more forceful @code{kill -9}. It can be used in +cases where @code{quit} doesn't work. + +@node Calling from Program +@section Calling the debugger from inside your Ruby program + +Running a program from the debugger adds a bit of overhead and slows +down your program a little. + +Furthermore, by necessity, debuggers change the operation of the +program they are debugging. And this can lead to unexpected and +unwanted differences. It has happened so often that the term +``Heisenbugs'' (see @url{http://en.wikipedia.org/wiki/Heisenbug}) was +coined to describe the situation where the addition of the use of a +debugger (among other possibilities) changes behavior of the program +so that the bug doesn't manifest itself anymore. + +There is another way to get into the debugger which adds no overhead +or slowdown until you reach the point at which you want to start +debugging. However here you must change the script and make an +explicit call to the debugger. Because the debugger isn't involved +before the first call, there is no overhead and the script will run +at the same speed as if there were no debugger. + +There are three parts to calling the debugger from inside the script, +``requiring'' the debugger code, telling the debugger to start +tracking things and then making the call calling the debugger to +stop. + +To get the debugger class accessible from your Ruby program: + +@smallexample +require 'rubygems' +require 'ruby-debug' +@end smallexample +(It is very likely that you've already require'd rubygems. If so, you +don't have to do that again.) These commands need to be done only +once. + +After @code{require 'ruby-debug'}, it's possible to set some of the +debugger variables influence preferences. For example if you want to +have @ttDBG run a @code{list} command every time it stops you set the +variable @code{Debugger.settings[:autolist]}. @pxref{Debugger.settings} has a +list of variable settings and the default values. Debugger settings +can also be set in @code{.rdebugrc} as debugger +commands. @pxref{Command Files} + +To tell the debugger to start tracking things: + +@smallexample +Debugger.start +@end smallexample + +There is also a @code{Debugger.stop} to turn off debugger tracking. If +speed is crucial, you may want to start and stop this around certain +sections of code. Alternatively, instead of issuing an explicit +@code{Debugger.stop} you can add a block to the @code{Debugger.start} +and debugging is turned on for that block. If the block of code raises +an uncaught exception that would cause the block to terminate, the +@code{stop} will occur. See @ref{Debugger.start with a block}. + +And finally to enter the debugger: + +@smallexample +debugger +@end smallexample + +As indicated above, when @code{debugger} is run a @code{.rdebugrc} +profile is read if that file exists. + +You may want to do enter the debugger at several points in the program +where there is a problem you want to investigate. And since +@code{debugger} is just a method call it's possible enclose it in a +conditional expression, for example: +@smallexample +debugger if 'bar' == foo and 20 == iter_count +@end smallexample + +Although each step does a very specific thing which offers great +flexibility, in order to make getting into the debugger easier the +three steps have been rolled into one command: +@smallexample +require "ruby-debug/debugger" +@end smallexample + +@node Debugger Command Reference +@chapter @code{ruby-debug} Command Reference + +@menu +* Command Interfaces:: The kinds of interface used to interact with ruby-debug +* Command Syntax:: How to give commands to the ruby-debug +* Command Output:: How rdebug presents its output +* Help:: How to ask for help (help) +* Control:: Controlling the debugger (quit, restart, interrupt) +* DisplayCommands:: Executing expressions on stop (display, undisplay) +* PrintCommands:: Evaluating and Printing Expressions (p, pp, ps, pp, irb) +* PrintVars:: Printing Variables (var) +* List:: Examining Program Source Files (list) +* Edit:: Editing source files (edit) +* FrameCommands:: Examining the stack frame (where, up, down, frame) +* Stopping:: Stopping and continuing (break, watch, step, cont...) +* ruby-debug settings:: rdebug-settings (set args, set autoeval, ...) +* Program Information:: Program Status (info) +@end menu + +@node Command Interfaces +@section Command Interfaces +There are several ways one can talk to @code{ruby-debug} and get +results. The simplest way is via a command-line interface directly +talking to the debugger. This is referred to below as a ``Local +Interface''. It's also possible to run the debugger and set up a port +by which some other process can connect and control the debug +session. This is called a ``Remote Interface''. When you want to gain +access to a remote interface you need to run @code{ruby-debug} using a +``Control Interface''. This interface might not be the same process as +the process running the debugged program and might not even be +running on the same computer. + +Other front-ends may use one of these and build on top and provide +other (richer) interfaces. Although many of the commands are available +on all interfaces some are not. Most of the time in this manual when +we talk about issuing commands describing the responses elicited, +we'll assume we are working with the local interface. + +@node Command Syntax +@section Command Syntax +Usually a command is put on a single line. There is no limit on how long +it can be. It starts with a command name, which is followed by +arguments whose meaning depends on the command name. For example, the +command @code{step} accepts an argument which is the number of times to +step, as in @code{step 5}. You can also use the @code{step} command with no +arguments. Some commands do not allow any arguments. + +Multiple commands can be put on a line by separating each with a +semicolon (@code{;}). You can disable the meaning of a semicolon to +separate commands by escaping it with a backslash. + +For example, if you have @code{autoeval} (@ref{Autoeval}) set, you +might want to enter the following code to compute the 5th Fibonacci +number: +@smallexample +# Compute the 5 Fibonaci number +(rdb:1) set autoeval on +(rdb:1) fib1=0; fib2=1; 5.times @{|temp| temp=fib1; fib1=fib2; fib2 += temp @} +SyntaxError Exception: compile error +/usr/bin/irb:10: syntax error, unexpected $end, expecting '@}' + 5.times @{|temp| temp=fib1 + ^ +(rdb:1) fib1=0\; fib2=1\; 5.times @{|temp| temp=fib1\; fib1=fib2\; fib2 += temp @} +5 +(rdb:1) fib2 +fib2 +8 +@end smallexample +You might also consider using the @code{irb} command, @ref{irb}, and +then you won't have to escape semicolons. + +A blank line as input (typing just @key{}) means to repeat the +previous command. + +In the ``local'' interface, the Ruby Readline module is used. It +handles line editing and retrieval of previous commands. Up arrow, for +example moves to the previous debugger command; down arrow moves to +the next more recent command (provided you are not already at the last +command). Command history is saved in file @code{.rdebug_hist}. A +limit is put on the history size. You can see this with the @code{show +history size} command. See @ref{History} for history parameters. + +@node Command Output +@section Command Output + +In the command-line interface, when @code{ruby-debug} is waiting for +input it presents a prompt of the form +@code{(rdb:}@emph{x}@code{)}. If debugging locally, @emph{x} will be +the thread number. Usual the main thread is 1, so often you'll see +@code{(rdb:1)}. In the control interface though @emph{x} will be +@code{ctrl} and in post-mortem debugging @code{post-mortem}. + +In the local interface, whenever @code{ruby-debug} gives an error +message such as for an invalid command, or an invalid location +position, it will generally preface the message with +@code{***}. However if annotation mode is on that the message is put +in a @code{begin-error} annotation and no @code{***} appears. + +@node Help +@section Getting help (@samp{help}) +@cindex on-line documentation +@menu +* Help for Subcommands:: +@end menu + +Once inside @code{ruby-debug} you can always ask it for information on +its commands, using the command @code{help}. + +@table @code +@kindex h @r{(@code{help})} +@kindex help @ovar{command-name} +@item help +@itemx h +You can use @code{help} (abbreviated @code{h}) with no arguments to +display a short list of named classes of commands: + +@flushleft +@smallexample +(rdb:1) @b{help} +ruby-debug help v@value{RDEBUG_VERSION} +Type 'help ' for help on a specific command + +Available commands: +backtrace delete enable help next quit show undisplay +break disable eval info p reload source up +catch display exit irb pp restart step var +condition down finish list ps save thread where +continue edit frame method putl set trace +@end smallexample +@end flushleft +@c the above line break eliminates huge line overfull... + +@end table + +@table @code +@item help @var{command} +With a command name as @code{help} argument, @DBG displays short +information on how to use that command. + +@smallexample +(rdb:1) @b{help list} +ruby-debug help v@value{RDEBUG_VERSION} +l[ist] list forward +l[ist] - list backward +l[ist] = list current line +l[ist] nn-mm list given lines +* NOTE - to turn on autolist, use 'set autolist' +(rdb:1) +@end smallexample +@end table + +@node Help for Subcommands +@subsection Help on Subcommands +A number of commands have many sub-parameters or +@emph{subcommands}. These include @code{info}, @code{set}, +@code{show}, @code{enable} and @code{disable}. + +When you ask for help for one of these commands, you will get help for +all of the subcommands that that command offers. Sometimes you may +want help that subcommand and to do this just follow the command with +its subcommand name. For example @code{help set annotate} will just +give help about the annotate command. Furthermore it will give longer +help than the summary information that appears when you ask for +help. You don't need to list the full subcommand name, but just enough +of the letters to make that subcommand distinct from others will +do. For example, @code{help set an} is the same as @code{help set annotate}. + +Some examples follow. +@example +(rdb:1) @b{help info} +Generic command for showing things about the program being debugged. +-- +List of info subcommands: +-- +info args -- Argument variables of current stack frame +info breakpoints -- Status of user-settable breakpoints +info catch -- Exceptions that can be caught in the current stack frame +info display -- Expressions to display when program stops +info file -- Info about a particular file read in +info files -- File names and timestamps of files read in +info global_variables -- Global variables +info instance_variables -- Instance variables of the current stack frame +info line -- Line number and file name of current position in source file +info locals -- Local variables of the current stack frame +info program -- Execution status of the program +info stack -- Backtrace of the stack +info thread -- List info about thread NUM +info threads -- information of currently-known threads +info variables -- Local and instance variables of the current stack frame +@end example + +@example +(rdb:1) @b{help info breakpoints} +Status of user-settable breakpoints. +Without argument, list info about all breakpoints. With an +integer argument, list info on that breakpoint. +@end example + +@example +(rdb:1) @b{help info br} +Status of user-settable breakpoints. +Without argument, list info about all breakpoints. With an +integer argument, list info on that breakpoint. +@end example + +@node Control +@section Controlling the debugger (@samp{quit}, @samp{restart}, @samp{interrupt}, @samp{source}) + +@menu +* Quit:: Quitting the debugger (quit) +* Restart:: Restarting Script execution (restart) +* Interrupt:: Interrupting the debugger (interrupt) +* Source:: Running Debugger commands (source) +@end menu + +@node Quit +@subsection Quit (@samp{quit}) +@table @code +@kindex quit @r{[}unconditionally@r{]} +@kindex q @r{(@code{quit})} +@item quit @r{[}unconditionally@r{]} +@item exit +@itemx q + +To exit @value{DBG}, use the @code{quit} command (abbreviated +@code{q}), or alias @code{exit}. + +A simple @code{quit} tries to terminate all threads in effect. + +Normally if you are in an interactive session, this command will +prompt to ask if you really want to quit. If you don't want any +questions asked, enter the ``unconditionally''. + +@end table + +@node Restart +@subsection Restart (@samp{restart}) +@table @code +@kindex restart @r{[}@var{program args}@r{]} +@kindex R @r{(@code{restart})} +@item restart +@itemx R + +Restart the program. This is is a re-exec - all debugger state is +lost. If command arguments are passed those are used. Otherwise the +last program arguments used in the last invocation are used. + +In not all cases will you be able to restart the program. First, the +program should have been invoked at the outset rather than having been +called from inside your program or invoked as a result of post-mortem +handling. + +Also, since this relies on the the OS @code{exec} call, this command +is available only if your OS supports that @code{exec}; OSX for +example does not (yet). +@end table + +@node Interrupt +@subsection Interrupt (@samp{interrupt}) +@table @code +@kindex interrupt +@kindex i +@item interrupt +@itemx i +Interrupt the program. Useful if there are multiple threads running. +@end table + +@node Source +@subsection Running Debugger Commands (@samp{source}) +@table @code +@kindex source @var{filename} +@item source @var{filename} +Execute the command file @var{filename}. + +The lines in a command file are executed sequentially. They are not +printed as they are executed. If there is an error, execution +proceeds to the next command in the file. For information about +command files that get run automatically on startup, @pxref{Command Files}. +@end table + +@node DisplayCommands +@section Executing expressions on stop (@samp{display}, @samp{undisplay}) +@cindex automatic display +@cindex display of expressions + +If you find that you want to print the value of an expression +frequently (to see how it changes), you might want to add it to the +@dfn{automatic display list} so that @value{DBG} evaluates a statement +each time your program stops or the statement is shown in line tracing. +Each expression added to the list is given a number to identify it; to +remove an expression from the list, you specify that number. The +automatic display looks like this: + +@smallexample +(rdb:1) display n +1: n = 3 +@end smallexample + +@noindent +This display shows item numbers, expressions and their current values. +If the expression is undefined or illegal the expression will be +printed but no value will appear. + +@smallexample +(rdb:1) display undefined_variable +2: undefined_variable = +(rdb:1) display 1/0 +3: 1/0 = +@end smallexample + +Note: this command uses @code{to_s} to in expressions; for example an +array @code{[1, 2]} will appear as @code{12}. For some datatypes like +an Array, you may want to call the @code{inspect} method, for example +@code{display ARGV.inspect} rather than @code{display ARGV}. + +@table @code +@kindex display @ovar{expr} +@item display @var{expr} +Add the expression @var{expr} to the list of expressions to display +each time your program stops or a line is printed when linetracing is +on (@pxref{DisplayCommands}). + +@item display +Display the current values of the expressions on the list, just as is +done when your program stops. + +@kindex undisplay @ovar{num} +@item undisplay @ovar{num} +@itemx delete display @var{num} +Remove item number @var{num} from the list of expressions to display. + +@kindex info display +@item info display +Show all display expressions + +@ifset GDB_COMPLETED +@code{undisplay} does not repeat if you press @key{RET} after using it. +(Otherwise you would just get the error @samp{No display number @dots{}}.) +@end ifset + +@kindex disable display +@item disable display @var{dnums}@dots{} +Disable the display of item numbers @var{dnums}. A disabled display +item is not printed automatically, but is not forgotten. It may be +enabled again later. + +@kindex enable display +@item enable display @var{dnums}@dots{} +Enable display of item numbers @var{dnums}. It becomes effective once +again in auto display of its expression, until you specify otherwise. + +@end table + +@node PrintCommands +@section Evaluating and Printing Expressions (@samp{p}, @samp{pp}, @samp{putl}, @samp{ps}, @samp{irb}) + +One way to examine and change data in your script is with the +@code{eval} command (abbreviated @code{p}). A similar command is +@code{pp} which tries to pretty print the result. Finally @code{irb} is +useful when you anticipate examining or changing a number of things, +and prefer not to have to preface each command, but rather work as one +does in @code{irb}. + +@menu +* eval:: eval or print an expression (eval, p) +* pp:: pretty print an expression (pp, ps, putl) +* irb:: running irb using the current context +@end menu + +@node eval +@subsection Printing an expression (@samp{eval}, @samp{p}) +@table @code +@kindex eval @var{expr} +@kindex p @r{(@code{eval})} +@item eval @var{expr} +@itemx p @var{expr} + +Use @code{eval} or @code{p} to evaluate a Ruby expression, @var{expr}, +same as you would if you were in @code{irb}. If there are many expressions +you want to look at, you may want to go into irb from the debugger. +@smallexample +@group +(rdb:p) p n +3 +(rdb:1) p "the value of n is #@{n@}" +"the value of n is 3" +(rdb:1) +@end group +@end smallexample +@end table + +@node pp +@subsection Pretty-Printing an expression (@samp{pp}, @samp{putl}, @samp{ps})) +@table @code +@item pp +@kindex pp @var{expr} +Evaluates and pretty-prints @var{expr} +@smallexample +@group +(rdb:1) @b{p $LOAD_PATH} +["/home/rocky/lib/ruby", "/usr/lib/ruby/site_ruby/1.8", "/usr/lib/ruby/site_ruby/1.8/i586-linux", "/usr/lib/ruby/1.8"] +(rdb:1) @b{pp $LOAD_PATH} +["/home/rocky/lib/ruby", + "/usr/lib/ruby/site_ruby/1.8", + "/usr/lib/ruby/site_ruby/1.8/i586-linux", + "/usr/lib/ruby/1.8"] +@end group +@end smallexample +@kindex putl +@item putl +If the value you want to print is an array, sometimes a columnized +list looks nicer: +@smallexample +@group +(rdb:1) @b{putl $LOAD_PATH} +/home/rocky/lib/ruby /usr/lib/ruby/site_ruby/1.8 +/usr/lib/ruby/site_ruby/1.8/i586-linux /usr/lib/ruby/1.8 +@end group +@end smallexample + +Note however that entries are sorted to run down first rather than +across. So in the example above the second entry in the list is +@code{/usr/lib/ruby/site_ruby/1.8/i586-linux} and the @emph{third} entry is +@code{/usr/lib/ruby/site_ruby/1.8}. + +If the value is not an array @code{putl} will just call pretty-print. +@kindex ps +@item ps +Sometimes you may want to print the array not only columnized, but +sorted as well. The list of debugger help commands appears this way, +and so does the output of the @code{method} commands. + +@smallexample +@group +(rdb:1) ps Kernel.private_methods +Digest initialize y +Pathname initialize_copy +Rational location_of_caller +active_gem_with_options method_added +alias_method method_removed +append_features method_undefined +attr module_function +attr_accessor private +attr_reader protected +attr_writer public +class_variable_get remove_class_variable +class_variable_set remove_const +define_method remove_instance_variable +extend_object remove_method +extended singleton_method_added +gcd singleton_method_removed +gem_original_require singleton_method_undefined +include timeout +included undef_method +@end group +@end smallexample + +If the value is not an array, @code{ps} will just call pretty-print. +See also the @code{methods}. +@end table + +@node irb +@subsection Run irb (@samp{irb}) +@table @code +@kindex irb +@item irb +Run an interactive ruby session (@code{irb}) with the bindings +environment set to the state you are in the program. + +When you leave irb and go back to the debugger command prompt we show +again the file, line and text position of the program in the same way +as when entered the debugger. If you issue a @command{list} without +location information, the default location used is the current line +rather than the position may have gotten updated via a prior +@command{list} command. +@smallexample +triangle.rb:4 +def triangle(n) +(rdb:1) @b{list} +[-1, 8] in /home/rocky/ruby/triangle.rb + 1 #!/usr/bin/env ruby + 2 # Compute the n'th triangle number - the hard way + 3 # triangle(n) == (n * (n+1)) / 2 +=> 4 def triangle(n) + 5 tri = 0 + 6 0.upto(n) do |i| + 7 tri += i + 8 end +@b{irb} +>> @b{(0..6).inject@{|sum, i| sum +=i@}} +=> 21 +>> @b{exit} +triangle.rb:4 +def triangle(n) +(rdb:1) @b{list # Note we get the same line range as before going into irb} +[-1, 8] in /home/rocky/ruby/triangle.rb + 1 #!/usr/bin/env ruby + 2 # Compute the n'th triangle number - the hard way + 3 # triangle(n) == (n * (n+1)) / 2 +=> 4 def triangle(n) + 5 tri = 0 + 6 0.upto(n) do |i| + 7 tri += i + 8 end +@end smallexample + +@end table + +@node PrintVars +@section Printing Variables (@samp{var}, @samp{method}) + +@table @code +@item var const @var{object} +@kindex var const @var{expr} +Show the constants of @var{object}. This is basically listing +variables and their values in @var{object}@code{.constant}. +@item var instance @var{object} +@kindex var instance @var{expr} +Show the instance variables of @var{object}. This is basically listing +@var{object}@code{.instance_variables}. +@item info instance_variables +@kindex info instance_variables +Show instance_variables of @code{@@self} +@item info locals +@kindex info locals +Show local variables +@item info globals +@kindex info globals +Show global variables +@item info variables +@kindex info variables +Show local and instance variables of @code{@@self} +@item method instance @var{object} +@kindex method instance @var{object} +Show methods of @var{object}. Basically this is the same as running +@code{ps object.instance_methods(false)} on @var{object}. +@item method iv @var{object} +@kindex method iv @var{object} +Show method instance variables of @var{object}. Basically this is the same as running +@smallexample + obj.instance_variables.each do |v| + puts "%s = %s\n" % [v, obj.instance_variable_get(v)] + end +@end smallexample +on @var{object}. +@item signature @var{object} +@kindex method signature @var{object} +Show procedure signature of method @var{object}. +@emph{This command is available only if the nodewrap is installed.} +@smallexample + def mymethod(a, b=5, &bock) + end + (rdb:1) @b{method sig mymethod} + Mine#mymethod(a, b=5, &bock) +@end smallexample +on @var{object}. +@item method @var{class-or-module} +@kindex method @var{class-or-module} +Show methods of the class or module, @var{class-or-module}. Basically +this is the same as running @code{ps object.methods} on @var{class-or-module}. +on @var{class-or-module}. +@end table + +@node List +@section Examining Program Source Files (@samp{list}) + +@cindex current line +@value{DBG} can print parts of your script's source. When your script +stops, @value{DBG} spontaneously prints the line where it stopped and +the text of that line. Likewise, when you select a stack frame +(@pxref{Selection}) @value{DBG} prints the line where execution in +that frame has stopped. Implicitly there is a default line +location. Each time a list command is run that implicit location is +updated, so that running several list commands in succession shows a +contiguous block of program text. + +You can print other portions of source files by giving an explicit +position as a parameter to the list command. + +If you use @value{DBG} through its Emacs interface, you may prefer to +use Emacs facilities to view source. +@c @pxref{GNU Emacs}. + +@kindex list @ovar{line-number} +@kindex l @r{(@code{list})} +To print lines from a source file, use the @code{list} command +(abbreviated @code{l}). By default, ten lines are printed. Fewer may +appear if there fewer lines before or after the current line to center +the listing around. + +There are several ways to specify what part of the file you want to print. +Here are the forms of the @code{list} command. + +@table @code +@item list @var{line-number} +@itemx l @var{line-number} +Print lines centered around line number @var{line-number} in the +current source file. + +@item list +@itemx l +Print more lines. If the last lines printed were printed with a +@code{list} command, this prints lines following the last lines +printed; however, if the last line printed was a solitary line printed +as part of displaying a stack frame (@pxref{Frames}), this prints lines +centered around that line. + +@item list - +@itemx l - +Print lines just before the lines last printed. +@item list @var{first}-@var{last} +Print lines between @var{first} and @var{last} inclusive. + +@item list = +Print lines centered around where the script is stopped. +@end table + +Repeating a @code{list} command with @key{RET} discards the argument, +so it is equivalent to typing just @code{list}. This is more useful +than listing the same lines again. An exception is made for an +argument of @samp{-}; that argument is preserved in repetition so that +each repetition moves up in the source file. + +@node Edit +@section Editing Source files (@samp{edit}) + +To edit the lines in a source file, use the @code{edit} command. The +editing program of your choice is invoked with the current line set to +the active line in the program. Alternatively, you can give a line +specification to specify what part of the file you want to print if +you want to see other parts of the program. + +You can customize to use any editor you want by using the +@code{EDITOR} environment variable. The only restriction is that your +editor (say @code{ex}), recognizes the following command-line syntax: +@smallexample +ex +@var{number} file +@end smallexample +The optional numeric value +@var{number} specifies the number of the +line in the file where to start editing. For example, to configure +@value{DBG} to use the @code{vi} editor, you could use these commands +with the @code{sh} shell: +@smallexample +EDITOR=/usr/bin/vi +export EDITOR +gdb @dots{} +@end smallexample +or in the @code{csh} shell, +@smallexample +setenv EDITOR /usr/bin/vi +gdb @dots{} +@end smallexample + +@table @code +@kindex edit @ovar{line-specification} +@item edit @ovar{line specification} +Edit line specification using the editor specified by the +@code{EDITOR} environment variable. +@end table + +@node FrameCommands +@section Examining the Stack Frame (@samp{where}, @samp{up}, @samp{down}, @samp{frame}) + +When your script has stopped, one thing you'll probably want to know +is where it stopped and some idea of how it got there. + +@cindex call stack +Each time your script performs a function or sends a message to a +method, or enters a block, information about this action is saved. +The frame stack then is this a history of the blocks that got you to +the point that you are currently stopped at.@footnote{More accurately +we should call this a ``block stack''; but we'll use the name that is +more commonly used. And internally in Ruby, there is ``FRAME'' +structure which is yet slightly different.} + +@cindex selected block +One entry in call stack is @dfn{selected} by @DBG{} and many +@DBG commands refer implicitly to the selected block. In +particular, whenever you ask @DBG to list lines without giving +a line number or location the value is found in the selected frame. +There are special @DBG commands to select whichever frame you +are interested in. @xref{Selection, ,Selecting a frame}. + +When your program stops, @DBG{} automatically selects the +currently executing frame and describes it briefly, similar to the +@code{frame} command. + +After switching frames, when you issue a @code{list} command without +any position information, the position used is location in the frame +that you just switched between, rather than a location that got +updated via a prior @code{list} command. + +@menu +* Frames:: Stack frames +* Backtrace:: Backtraces (where) +* Selection:: Selecting a frame (up, down, frame) + +@end menu + +@node Frames +@subsection Stack frames + +@cindex frame, definition +@cindex stack frame +The block stack is divided up into contiguous pieces called @dfn{stack +frames}, @dfn{frames}, or @dfn{blocks} for short; each frame/block has +a scope associated with it; It contains a line number and the +source-file name that the line refers. If the frame/block is the beginning +of a method or function it also contains the function name. + +@cindex initial frame +@cindex outermost frame +@cindex innermost frame +When your script is started, the stack has only one frame, that of the +function @code{main}. This is called the @dfn{initial} frame or the +@dfn{outermost} frame. Each time a function is called, a new frame is +made. Each time a function returns, the frame for that function invocation +is eliminated. If a function is recursive, there can be many frames for +the same function. The frame for the function in which execution is +actually occurring is called the @dfn{innermost} frame. This is the most +recently created of all the stack frames that still exist. + +@cindex frame number +@value{DBG} assigns numbers to all existing stack frames, starting with +zero for the innermost frame, one for the frame that called it, +and so on upward. These numbers do not really exist in your script; +they are assigned by @value{DBG} to give you a way of designating stack +frames in @value{DBG} commands. + +@node Backtrace +@subsection Backtraces (@samp{where}) + +@cindex backtraces +@cindex tracebacks +@cindex stack traces +A backtrace is essentially the same as the call stack: a summary of +how your script got where it is. It shows one line per frame, for +many frames, starting with the place that you are stopped at (frame +zero), followed by its caller (frame one), and on up the stack. + +@table @code +@kindex where +@kindex w @r{(@code{where})} +@itemx where +Print the entire stack frame; @code{info stack} is an alias for this command. +Each frame is numbered and can be referred to in the @code{frame} +command; @code{up} and @code{down} add or subtract respectively to +frame numbers shown. The position of the current frame is marked with +@code{-->}. + +@smallexample +(rdb:1) where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line /tmp/gcd.rb:6 + #1 at line /tmp/gcd.rb:19 +@end smallexample + +@ifset FINISHED +@item backtrace @var{n} +@itemx bt @var{n} +@itemx where @var{n} +@itemx T @var{n} +Similar, but print only the innermost @var{n} frames. + +@item backtrace -@var{n} +@itemx bt -@var{n} +@itemx where -@var{n} +@itemx T -@var{n} +Similar, but print only the outermost @var{n} frames. +@end ifset +@end table + +@node Selection +@subsection Selecting a frame (@samp{up}, @samp{down}, @samp{frame}) + +Commands for listing source code in your script work on whichever +stack frame is selected at the moment. Here are the commands for +selecting a stack frame; all of them finish by printing a brief +description of the stack frame just selected. + +@table @code +@kindex up @ovar{n} +@item up @ovar{n} +Move @var{n} frames up the stack. For positive numbers @var{n}, this +advances toward the outermost frame, to higher frame numbers, to +frames that have existed longer. Using a negative @var{n} is the same thing +as issuing a @code{down} command of the absolute value of the @var{n}. +Using zero for @var{n} does no frame adjustment, but since the current +position is redisplayed, it may trigger a resynchronization if there is +a front end also watching over things. + +@var{n} defaults to one. You may abbreviate @code{up} as @code{u}. + +@kindex down @ovar{n} +@item down @ovar{n} +Move @var{n} frames down the stack. For positive numbers @var{n}, this +advances toward the innermost frame, to lower frame numbers, to frames +that were created more recently. Using a negative @var{n} is the same +as issuing a @code{up} command of the absolute value of the @var{n}. +Using zero for @var{n} does no frame adjustment, but since the current +position is redisplayed, it may trigger a resynchronization if there is +a front end also watching over things. + +@var{n} defaults to one. +@end table + +@table @code +@kindex frame @r{[}@ovar{n} @r{[}thread @var{thread-num}@r{]}@r{]} +@cindex current stack frame +@item frame @ovar{n} @r{[}thread @var{thread-num}@r{]} +The @code{frame} command allows you to move from one stack frame to +another, and to print the stack frame you select. @var{n} is the the +stack frame number or 0 if no frame number is given; @code{frame 0} +then will always show the current and most recent stack frame. + +If a negative number is given, counting is from the other end of the +stack frame, so @code{frame -1} shows the least-recent, outermost or +most ``main'' stack frame. + +Without an argument, @code{frame} prints the current stack +frame. Since the current position is redisplayed, it may trigger a +resynchronization if there is a front end also watching over +things. + +If a thread number is given then we set the context for evaluating +expressions to that frame of that thread. +@end table + +@node Stopping +@section Stopping and Resuming Execution + +One important use of a debugger is to stop your program @emph{before} +it terminates, so that if your script runs into trouble you can +investigate and find out why. However should your script accidentally +continue to termination, it can be arranged for @DBG to not to leave +the debugger without your explicit instruction. That way, you can +restart the program using the same command arguments. + +Inside @value{DBG}, your script may stop for any of several reasons, +such as a signal, a breakpoint, or reaching a new line after a +debugger command such as @code{step}. You may then examine and +change variables, set new breakpoints or remove old ones, and then +continue execution. + +@menu +* Breakpoints:: Breakpoints (break, catch, delete) +* Disabling:: Disabling breakpoints (disable, enable) +* Conditions:: Break conditions (condition) +* Resuming Execution:: Resuming execution (continue, step, next, finish) +@end menu + +@node Breakpoints +@subsection Breakpoints (@samp{break}, @samp{catch}, @samp{delete}) + +@cindex breakpoints +A @dfn{breakpoint} makes your script stop whenever a certain point in +the program is reached. For each breakpoint, you can add conditions to +control in finer detail whether your script stops. + +You specify the place where your script should stop with the +@code{break} command and its variants. + +@cindex breakpoint numbers +@cindex numbers for breakpoints +@value{ttDBG} assigns a number to each breakpoint when +you create it; these numbers are successive integers starting with +one. In many of the commands for controlling various features of +breakpoints you use the breakpoint number to say which breakpoint you +want to change. Each breakpoint may be @dfn{enabled} or +@dfn{disabled}; if disabled, it has no effect on your script until you +enable it again. + + +@table @code +@kindex break @ovar{location} +@kindex b @r{(@code{break})} +@item break +Set a breakpoint at the current line. + +@item break @var{linenum} +Set a breakpoint at line @var{linenum} in the current source file. +The current source file is the last file whose source text was printed. +The breakpoint will stop your script just before it executes any of the +code on that line. + +@item break @var{filename}:@var{linenum} +Set a breakpoint at line @var{linenum} in source file @var{filename}. + +What may be a little tricky when specifying the filename is getting +the name recognized by the debugger. If you get a message the message +``@code{No source file named ...}'', then you may need to qualify the +name more fully. To see what files are loaded you can use the @code{info +files} or @code{info file} commands. If you want the name @code{rdebug} thinks +of as the current file, use @code{info line}. + +Here's an example: +@example +$ @b{rdebug ~/ruby/gcd.rb 3 5} +/home/rocky/ruby/gcd.rb:4 # Note this is the file name +def gcd(a, b) +(rdb:1) @b{break gcd.rb:6} +*** No source file named gcd.rb +(rdb:1) @b{info line} +Line 4 of "/home/rocky/ruby/gcd.rb" +(rdb:1) @b{break /home/rocky/ruby/gcd.rb:6} +Breakpoint 1 file /home/rocky/ruby/gcd.rb, line 6 +(rdb:1) @b{break ~/ruby/gcd.rb:10} # tilde expansion also works +Breakpoint 2 file /home/rocky/ruby/gcd.rb, line 10 +(rdb:1) @b{info file gcd.rb} +File gcd.rb is not cached +(rdb:1) @b{info file /home/rocky/ruby/gcd.rb} +File /home/rocky/ruby/gcd.rb + 19 lines +@end example + +@item break @var{class}:@var{method} +Set a breakpoint in class @var{class} method @var{method}. You can +also use a period @code{.} instead of a colon @code{:}. Note that two +colons @code{::} are not used. Also note a class @emph{must} be +specified here. If the method you want to stop in is in the main class +(i.e. the class that @code{self} belongs to at the start of the +program), then use the name @code{Object}. + +@kindex catch @ovar{exception} @r{[} on | 1 | off | 0 @r{]} +@kindex cat @r{(@code{catch})} +@item catch @ovar{exception} @r{[} on | 1 | off | 0 @r{]} +Set catchpoint to an exception. Without an exception name show catchpoints. + +With an ``on'' or ``off'' parameter, turn handling the exception on or +off. To delete all exceptions type ``catch off''. + +@cindex delete breakpoints +@kindex delete @ovar{breakpoints} +@kindex del @r{(@code{delete})} +@item delete @ovar{breakpoints} +Delete the breakpoints specified as arguments. + +If no argument is specified, delete all breakpoints (@DBG asks +confirmation. You can abbreviate this command as @code{del}. +@kindex info breakpoints +@cindex @code{$_} and @code{info breakpoints} +@item info breakpoints @ovar{n} +@itemx info break @ovar{n} +Print a table of all breakpoints set and not deleted, with the +following columns for each breakpoint: + +@table @emph +@item Breakpoint Numbers (@samp{Num}) +@item Enabled or Disabled (@samp{Enb}) +Enabled breakpoints are marked with @samp{1}. @samp{0} marks breakpoints +that are disabled (not enabled). +@item File and Line (@samp{file:line}) +The filename and line number inside that file where of breakpoint in +the script. The file and line are separated with a colon. +@item Condition +A condition (an arithmetic expression) which when true causes the +breakpoint to take effect. +@end table +@noindent +If a breakpoint is conditional, @code{info break} shows the condition on +the line following the affected breakpoint; breakpoint commands, if any, +are listed after that. + +@code{info break} with a breakpoint number @var{n} as argument lists +only that breakpoint. + +Examples: +@example +(rdb:1) @b{info break} +Breakpoints at following places: +Num Enb What +1 y gcd.rb:3 +2 y gcb.rb:28 if n > 1 +(rdb:1) @b{info break 2} +2 y gcb.rb:28 if n > 1 +@end example +@end table + +@node Disabling +@subsection Disabling breakpoints (@samp{disable}, @samp{enable}) + +Rather than deleting a breakpoint, you might +prefer to @dfn{disable} it. This makes the breakpoint inoperative as if +it had been deleted, but remembers the information on the breakpoint so +that you can @dfn{enable} it again later. + +You disable and enable breakpoints and catchpoints with the +@code{enable} and @code{disable} commands, optionally specifying one +or more breakpoint numbers as arguments. Use @code{info break} to +print a list of breakpoints and catchpoints if you do not know which +numbers to use. + +A breakpoint or catchpoint can have any different +states of enablement: + +@itemize @bullet +@item +Enabled. The breakpoint stops your program. A breakpoint set +with the @code{break} command starts out in this state. +@item +Disabled. The breakpoint has no effect on your program. +@end itemize + +You can use the following commands to enable or disable breakpoints +and catchpoints: + +@table @code +@kindex disable breakpoints +@item disable @var{breakpoints} +Disable the specified breakpoints---or all breakpoints, if none are +listed. A disabled breakpoint has no effect but is not forgotten. All +options such as ignore-counts, conditions and commands are remembered in +case the breakpoint is enabled again later. You may abbreviate +@code{disable} as @code{dis}. + +@kindex enable breakpoints +@item enable @var{breakpoints} +Enable the specified breakpoints (or all defined breakpoints). They +become effective once again in stopping your program. + +@end table + +Breakpoints that you set are initially enabled; subsequently, they +become disabled or enabled only when you use one of the commands +above. (The command @code{until} can set and delete a breakpoint of +its own, but it does not change the state of your other breakpoints; +see @ref{Resuming Execution, ,Resuming Execution}.) + +@node Conditions +@subsection Break conditions (@samp{condition}) +@cindex conditional breakpoints +@cindex breakpoint conditions + +The simplest sort of breakpoint breaks every time your script reaches +a specified place. You can also specify a @dfn{condition} for a +breakpoint. A condition is just a Ruby expression. + +Break conditions can be specified when a breakpoint is set, by using +@samp{if} in the arguments to the @code{break} command. A breakpoint +with a condition evaluates the expression each time your script +reaches it, and your script stops only if the condition is +@emph{true}. They can also be changed at any time +with the @code{condition} command. + +@ifset FINISHED +You can also use the @code{if} keyword with the @code{watch} command. +The @code{catch} command does not recognize the @code{if} keyword; +@code{condition} is the only way to impose a further condition on a +catchpoint. +@end ifset + +@table @code +@kindex condition +@item condition @var{bnum} @var{expression} +Specify @var{expression} as the break condition for breakpoint +@var{bnum}. After you set a condition, breakpoint @var{bnum} stops +your program only if the value of @var{expression} is true (nonzero). + +@item condition @var{bnum} +Remove the condition from breakpoint number @var{bnum}. It becomes +an ordinary unconditional breakpoint. +@end table + +@ifset FINISHED +When you use @code{condition}, @DBG checks @var{expression} +immediately for syntactic correctness, and to determine whether +symbols in it have referents in the context of your breakpoint. If +@var{expression} uses symbols not referenced in the context of the +breakpoint, @DBG prints an error message: + +@example +No symbol "foo" in current context. +@end example +@end ifset + +@noindent +The debugger does not actually evaluate @var{expression} at the time +the @code{condition} command (or a command that sets a breakpoint with +a condition, like @code{break if @dots{}}) is given, however. + +Examples; +@example +condition 1 x>5 # Stop on breakpoint 0 only if x>5 is true. +condition 1 # Change that! Unconditionally stop on breakpoint 1. +@end example + +@node Resuming Execution +@subsection Resuming Execution (@samp{step}, @samp{next}, @samp{finish}, @samp{continue}) + +A typical technique for using stepping is to set a breakpoint +(@pxref{Breakpoints}) at the beginning of the function or the section +of your script where a problem is believed to lie, run your script +until it stops at that breakpoint, and then step through the suspect +area, examining the variables that are interesting, until you see the +problem happen. + +@cindex stepping +@cindex continuing +@cindex resuming execution +@dfn{Continuing} means resuming program execution until your script +completes normally. In contrast, @dfn{stepping} means executing just +one more ``step'' of your script, where ``step'' may mean either one +line of source code. Either when continuing or when stepping, +your script may stop even sooner, due to a breakpoint or a signal. + +@menu +* Step:: running the next statement (step) +* Next:: running the next statement skipping over functions (next) +* Finish:: running until the return of a function or ``source'' (finish) +* Continue:: continuing execution (continue) +@end menu + +@node Step +@subsubsection Step (@samp{step}) +@table @code +@kindex step @r{[}+@r{]} @ovar{count} +@kindex s @r{(@code{step})} +@item step @r{[}+-@r{]} @ovar{count} +Continue running your program until the next logical stopping point +and return control to @value{DBG}. This command is abbreviated +@code{s}. + +Like, the programming Lisp, Ruby tends implemented in a highly +expression-oriented manner. Therefore things that in other languages +that may appear to be a single statement are implemented in Ruby as +several expressions. For example, in an ``if'' statement or looping +statements a stop is made after the expression is evaluated but before +the test on the expression is made. + +So it is common that a lines in the program will have several stopping +points where in other debuggers of other languages there would be only +one. Or you may have several statements listed on a line. + +When stepping it is not uncommon to want to go to a different line on +each step. If you want to make sure that on a step you go to a +@emph{different} position, add a plus sign (@samp{+}). + +@emph{Note: step+ with a number count is not the same as issuing +count step+ commands. Instead it uses count-1 step commands followed +by a step+ command. For example, @code{step+ 3} is the +same as @code{step; step; step+}, not @code{step+; step+; step+}} + +If you find yourself generally wanting to use @code{step+} rather +than @code{step}, you may want to consider using @code{set +forcestep}, (@pxref{Forcestep}). + +If you have @code{forcestep} set on but want to temporarily disable it +for the next step command, append a minus, or @code{step-}. + +With a count, @code{step} will continue running as normal, but do so +@var{count} times. If a breakpoint is reached, or a signal not +related to stepping occurs before @var{count} steps, stepping stops +right away. +@end table + +@node Next +@subsubsection Next (@samp{next}) +@table @code +@kindex next @r{[}+-@r{]} @ovar{count} +@kindex n @r{(@code{next})} +@item next @r{[}+@r{]} @ovar{count} +This is similar to @code{step}, but function or method calls that +appear within the line of code are executed without stopping. As with +step, if you want to make sure that on a step you go to a +@emph{different} position, add a plus sign (@samp{+}). Similarly, +appending a minus disables a @code{forcestep} temporarily, and an +argument @var{count} is a repeat count, as for @code{step}. +@end table + +@node Finish +@subsubsection Finish (@samp{finish}) +@table @code +@kindex finish @ovar{frame-number} +@item finish @ovar{frame-number} +Execute until selected stack frame returns. If no frame number is +given, we run until the currently selected frame returns. The +currently selected frame starts out the most-recent frame or 0 if no +frame positioning (e.g@: @code{up}, @code{down} or @code{frame}) has +been performed. If a frame number is given we run until @var{frame} frames +returns. + +If you want instead to terminate the program and debugger entirely, +use @code{quit} (@pxref{Quitting the debugger, ,Quitting the debugger}). + +@emph{Note:} Releases before Ruby version 1.8.7 show the return line +as the first line of the method. Starting with version 1.8.7, the last +line executed will be shown as the return +line. @url{http://rubyforge.org/tracker/?func=detail&atid=22040&aid=18749&group_id=426} + +@end table + +@node Continue +@subsubsection Continue (@samp{continue}) +@table @code +@kindex continue @ovar{line-specification} +@kindex c @r{(@code{continue})} +@item continue @ovar{line-specification} +@itemx c @ovar{line-specification} +Resume program execution, at the address where your script last +stopped; any breakpoints set at that address are bypassed. + +The optional argument @var{line-specification} allows you to specify a +line number to set a one-time breakpoint which is deleted when that +breakpoint is reached. + +Should the program stop before that breakpoint is reached, for +example, perhaps another breakpoint is reached first, in +a listing of the breakpoints you won't see this entry in the list of +breakpoints. +@end table + +@node ruby-debug settings +@section ruby-debug settings (@samp{set args}, @samp{set autoeval}..) + +You can alter the way ruby-debug interacts with you using @code{set} +commands. + +The various parameters to @code{set} are given below. Each parameter +name needs to to be only enough to make it unique. For example +@code{set force} is a suitable abbreviation for @code{set forcestep}. +The letter case is not important, so @code{set FORCE} or @code{set +Force} are also suitable abbreviations. + +Many @code{set} commands are either ``on'' or ``off'', and you can +indicate which way you want set by supplying the corresponding +word. The number 1 can be used for ``on'' and 0 for ``off''. If none +of these is given, we will assume ``on''. A deprecated way of turning +something off is by prefacing it with ``no''. + +Each @code{set} command has a corresponding @code{show} command which +allows you to see the current value. + +@menu +* Args:: Annotation Level +* Autoeval:: Evaluate unrecognized commands +* Autolist:: Execute ``list'' command on every breakpoint +* Autoirb:: Invoke IRB on every stop +* Autoreload:: Reload source code when changed +* Basename:: Report file basename only showing file names +* Callstyle:: Show Report file basename only showing file names +* Forcestep:: Make sure 'next/step' commands always move to a new line +* Fullpath:: Display full file names in frames +* History:: Generic command for showing command history parameters. +* Keepframebindings:: Save frame binding on each call +* Linetrace:: line execution tracing +* Linetrace+:: line tracing style +* Listsize:: Number of lines to try to show in a 'list' command +* Post-mortem:: Whether post-mortem handling is in effect. +* Trace:: Display stack trace when 'eval' raises exception +* Width:: Number of characters the debugger thinks are in a line +@end menu + +@node Args +@subsection Set/Show args + +@table @code +@kindex set args @ovar{parameters} +@item set args @ovar{parameters} +Specify the arguments to be used if your program is rerun. If +@code{set args} has no arguments, @code{restart} executes your program +with no arguments. Once you have run your program with arguments, +using @code{set args} before the next @code{restart} is the only way to run +it again without arguments. + +@kindex show args +@item show args +Show the arguments to give your program when it is started. +@end table + +@node Autoeval +@subsection Set/Show auto-eval + +@table @code +@kindex set autoeval @r{[} on | 1 | off | 0 @r{]} +@item set autoeval @r{[} on | 1 | off | 0 @r{]} +Specify that debugger input that isn't recognized as a command should +be passed to Ruby for evaluation (using the current debugged program +namespace). Note however that we @emph{first} check input to see if it +is a debugger command and @emph{only} if it is not do we consider it +as Ruby code. This means for example that if you have variable called +@code{n} and you want to see its value, you could use @code{p n}, +because just entering @code{n} will be interpreted as the debugger +``next'' command. + +See also @ref{irb} and @ref{Autoirb}. + +When autoeval is set on, you'll get a different error message when you +invalid commands are encountered. Here's a session fragment to show +the difference +@smallexample +(rdb:1) @b{stepp} +Unknown command +(rdb:1) @b{set autoeval on} +autoeval is on. +(rdb:1) @b{stepp} +NameError Exception: undefined local variable or method `stepp' for ... +@end smallexample + +@kindex show autoeval +@item show args +Shows whether Ruby evaluation of debugger input should occur or not. +@end table + +@node Autolist +@subsection Execute ``list'' command on every breakpoint + +@node Autoirb +@subsection Set/Show auto-irb + +@table @code +@kindex set autoirb @r{[} on | 1 | off | 0 @r{]} +@item set autoirb @r{[} on | 1 | off | 0 @r{]} + +When your program stops, normally you go into a debugger command loop +looking for debugger commands. If instead you would like to directly +go into an irb shell, set this on. See also @ref{Autoeval} or +@ref{irb} if you tend to use debugger commands but still want Ruby +evaluation occasionally. + +@kindex show autoirb +@item show autoirb +Shows whether the debugger will go into irb on stop or not. +@end table + +@node Autoreload +@subsection Set/Show auto-reload +@table @code +@kindex set autoreload @r{[} on | 1 | off | 0 @r{]} +Set this on if the debugger should check to see if the source has +changed since the last time it reread in the file if it has. +@end table + +@node Basename +@subsection Set/Show basename + +@table @code +@kindex set basename @r{[} on | 1 | off | 0 @r{]} +@item set basename @r{[} on | 1 | off | 0 @r{]} +Source filenames are shown as the shorter ``basename'' +only. (Directory paths are omitted). This is useful in running the +regression tests and may useful in showing debugger examples as in +this text. You may also just want less verbose filename display. + +By default filenames are shown as with their full path. + +@kindex show basename +@item show basename +Shows the whether filename display shows just the file basename or not. +@end table + +@node Callstyle +@subsection Set/Show call style + +@table @code +@ifset FINISHED +@kindex set callstyle @r{[} short | last | tracked @r{]} +@item set forcestep @r{[} short | last | tracked @r{]} +@else +@kindex set callstyle @r{[} short | last +@item set forcestep @r{[} short | last +@end ifset + +Sets how you want call parameters displayed; @code{short} shows just +the parameter names; +@ifset FINISHED +@code{last} shows the parameter names and the +class of these variables as they currently exist. Note the type could +have changed between when the call and its current +values. +@end ifset +@code{tracked} is the most accurate but this adds +overhead. On every call, scalar values of the parameters get +saved. For non-scalar values the class is saved. +@end table + +@node Forcestep +@subsection Set/Show Forces Different Line Step/Next + +@table @code +@kindex set forcestep @r{[} on | 1 | off | 0 @r{]} +@item set forcestep @r{[} on | 1 | off | 0 @r{]} + +Due to the interpretive, expression-oriented nature of the Ruby +Language and implementation, each line often contains many possible +stopping points, while in a debugger it is often desired to treat each +line as an individual stepping unit. + +Setting forcestep on will cause each @code{step} or @code{next} +command to stop at a different line number. See also @ref{Step} and +@ref{Next}. + +@kindex show forcestep +@item show forcestep +Shows whether forcestep is in effect or not. +@end table + +@node Fullpath +@subsection Set/Show Frame full path + +@node History +@subsection Command History Parameters +@table @code +@item show commands +@kindex show commands +Display the last ten commands in the command history. + +@item show commands @var{n} +@kindex show commands @var{n} +Print ten commands centered on command number @var{n}. + +@item show history filename +@kindex show history filename +Show the filename in which to record the command history +(the list of previous commands of which a record is kept). + +@item set history save @r{[} on | 1 | off | 0 @r{]} +@kindex set history save @r{[} on | 1 | off | 0 @r{]} +Set whether to save the history on exit. + +@item show history save +@kindex show history save +Show saving of the history record on exit. + +@item set history size @var{number} +@kindex set history size @var{number} +Set the maximum number of commands to save in the history. + +@item show history size +@kindex show history size +Show the size of the command history, i.e. the number of previous +commands to keep a record of. +@end table + +@node Keepframebindings +@subsection Save frame binding on each call + +@node Linetrace +@subsection Set/Show Line tracing + +@table @code +@kindex set linetrace @r{[} on | 1 | off | 0 @r{]} +@item set linetrace @r{[} on | 1 | off | 0 @r{]} + +Setting linetrace on will cause lines to be shown before run. + +@kindex show linetrace +@item show linetrace +Shows whether line tracing is in effect or not. +@end table + +@node Linetrace+ +@subsection Set/Show Line tracing style + +@table @code +@kindex set linetrace+ @r{[} on | 1 | off | 0 @r{]} +@item set linetrace+ @r{[} on | 1 | off | 0 @r{]} + +Setting linetrace+ on will cause consecutive trace lines not to be a +duplicate of the preceding line-trace line. Note however that this +setting doesn't by itself turn on or off line tracing. + +@kindex show linetrace+ +@item show linetrace +Shows whether the line tracing style is to show all lines or remove +duplicates linetrace lines when it is a repeat of the previous line. +@end table + +@node Listsize +@subsection Set/Show lines in a List command + +@table @code +@kindex set listsize @var{number-of-lines} +@item set listsize @var{number-of-lines} +Set number of lines to try to show in a @code{list} command. +@kindex show listsize +@item show listsize +Shows the list-size setting. +@end table + +@node Post-mortem +@subsection Show Post-mortem handling +@table @code +@kindex show post-mortem +Shows wither post-mortem debugging is in effect. Right now we don't +have the ability to change the state inside the debugger. +@end table + +@node Trace +@subsection Display stack trace when 'eval' raises exception + +@node Width +@subsection Set/Show Line width + +@table @code +@kindex set width @var{column-width} +@item set width @var{column-width} +Set number of characters the debugger thinks are in a line. +We also change OS environment variable @code{COLUMNS}. +@kindex show width +@item show width +Shows the current width setting. +@end table + +@node Program Information +@section Program Information (@samp{info}) + +This @code{info} command (abbreviated @code{i}) is for describing the +state of your program. For example, you can list the current +parameters with @code{info args}, or list the breakpoints you have set +with @code{info breakpoints} or @code{info watchpoints}. You can get +a complete list of the @code{info} sub-commands with @w{@code{help +info}}. + +@table @code +@kindex info args + +@item info args +Method arguments of the current stack frame. +@kindex info breakpoints + +@item info breakpoints +Status of user-settable breakpoints +@kindex info display + +@item info display +All display expressions. +@kindex info files + +@item info files +Source files in the program. +@kindex info file + +@item info file @var{filename} @ovar{all|lines|mtime|sha1} +Information about a specific file. Parameter @code{lines} gives the +number of lines in the file, @code{mtime} shows the modification time +of the file (if available), @code{sha1} computes a SHA1 has of the +data of the file. @code{all} gives all of the above information. + +@kindex info line +@item info line +Line number and file name of current position in source. +@kindex info locals +@item info locals +Local variables of the current stack frame. +@kindex info program +@item info program +Display information about the status of your program: whether it is +running or not and why it stopped. If an unhandled exception occurred, +the exception class and @code{to_s} method is called. +@kindex info stack +@item info stack +Backtrace of the stack. An alias for @code{where}. @xref{Backtrace}. +@kindex info thread +@item info thread @ovar{thread-number} @r{[} terse | verbose@r{]} +If no thread number is given, we list info for all +threads. @code{terse} and @code{verbose} options are possible. If terse, +just give summary thread name information. See information under @code{info threads} for +more detail about this summary information. + +If @code{verbose} is appended to the end of the command, then the entire +stack trace is given for each thread. + +@kindex info threads @r{[} terse | verbose@r{]} +@item info threads + +List information about currently-known threads. This information +includes whether the thread is current (+), if it is suspended ($), or +ignored (!); the thread number and the top stack item. If +@code{verbose} is given then the entire stack frame is shown. Here is +an example: + +@smallexample +(rdb:7) info threads + 1 # ./test/thread1.rb:27 + !2 # + 3 # ./test/thread1.rb:11 + 4 # ./test/thread1.rb:11 + 5 # ./test/thread1.rb:11 + 6 # ./test/thread1.rb:11 ++ 7 # ./test/thread1.rb:14 +(rdb:1) +@end smallexample + +Thread 7 is the current thread since it has a plus sign in front. Thread 2 is +ignored since it has a @code{!}. A ``verbose'' listing of the above: + +@smallexample +(rdb:7) info threads verbose + 1 # + #0 Integer.join at line test/thread1.rb:27 + #1 at line test/thread1.rb:27 + !2 # + 3 # + #0 sleep(count#Fixnum) at line test/thread1.rb:11 + #1 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:11 + #2 at line test/thread1.rb:23 + 4 # + #0 sleep(count#Fixnum) at line test/thread1.rb:11 + #1 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:11 + #2 at line test/thread1.rb:23 + 5 # + #0 sleep(count#Fixnum) at line test/thread1.rb:11 + #1 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:11 + #2 at line test/thread1.rb:23 + 6 # + #0 sleep(count#Fixnum) at line test/thread1.rb:11 + #1 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:11 + #2 at line test/thread1.rb:23 ++ 7 # + #0 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:14 + #1 at line test/thread1.rb:23 +@end smallexample + +@kindex info variables +@item info variables +Local and instance variables. +@end table + +@node Post-Mortem Debugging +@chapter Post-Mortem Debugging +@cindex post-mortem debugging + +It is also to possible enter the debugger when you have an uncaught +exception that is about to terminate our program. This is called +@emph{post-mortem debugging}. In this state many, of the debugger commands +for examining variables and moving around in the stack still +work. However some commands, such as those which imply a continuation +of running code, no longer work. + +The most reliable way to set up post-mortem debugging is to use the +@option{--post-mortem} option in invoking @code{rdebug}. See @ref{rdebug +command-line options}. This traps/wraps at the debugger ``load'' of +your Ruby script. When this is done, your program is stopped after +the exception takes place, but before the stack has been +unraveled. (Alas, it would be nice to if one could allow resetting the +exception and continuing, but details of code in Ruby 1.8's +@code{eval.c} prevent this.) + +If however you haven't invoked @code{rdebug} at the outset, but +instead call @code{ruby-debug} from inside your program, to set up +post-mortem debugging set the @code{post_mortem} key in +@code{Debugger.start}. Here's an example modified from +@url{http://www.datanoise.com/articles/2006/12/20/post-mortem-debugging}: + +@smallexample + $ @b{cat t.rb } + require 'rubygems' + require 'ruby-debug' ; Debugger.start(:post_mortem => true) + + def t1 + raise 'test' + end + def t2 + t1 + end + t2 + + $ @b{ruby t.rb } + t.rb:8: raise 'test' + (rdb:post-mortem) @b{l=} + [3, 12] in t.rb + 3 + 4 Debugger.start + 5 Debugger.post_mortem + 6 + 7 def t1 + => 8 raise 'test' + 9 end + 10 def t2 + 11 t1 + 12 end + (rdb:post-mortem) +@end smallexample + +Alternatively you can call @code{Debugger.post_mortem()} after rdebug has +been started. The @code{post_mortem()} method can be called in two +ways. Called without a block, it installs a global @code{at_exit()} hook +that intercepts exceptions not handled by your Ruby script. In +contrast to using the @option{--post-mortem} option, when this hook +occurs after the call stack has been rolled back. (I'm not sure if +this in fact makes any difference operationally; I'm just stating it +because that's how it works.) + +If you know that a particular block of code raises an exception you +can enable post-mortem mode by wrapping this block inside a +@code{Debugger.post_mortem} block + +@smallexample +def offender + 1/0 +end +... +require "ruby-gems" +require "ruby-debug" +Debugger.post_mortem do + ... + offender + ... +end +@end smallexample + +Once inside the debugger in post-mortem debugging, the prompt should +be @code{(rdb:post-mortem)}. + +@node Debugger Module and Class +@chapter The Debugger Module and Class + +@menu +* Debugger Module:: ruby-debug's Debugger module +* Debugger Class:: Debugger class +* Kernel routines:: Routines added to Kernel +@end menu + +@node Debugger Module +@section The Debugger Module + +@menu +* Debugger.run:: +@ifset LATER +* Debugger.post-mortem:: +@end ifset +* Debugger.context:: +* Debugger.settings:: +@end menu + +@node Debugger.run +@subsection @code{Debugger.start}, @code{Debugger.started?}, @code{Debugger.stop}, @code{Debugger.run_script} + +In order to provide better debugging information regarding the stack +frame(s) across all threads, ruby-debug has to intercept each call, +save some information and on return remove it. Possibly, in Ruby 1.9 +possibly this will not be needed. Therefore one has to issue call to +indicate start saving information and another call to stop. Of course, +If you call ruby-debug from the outset via @code{rdebug} this is done +for you. + +@table @code +@item Debugger.start(@ovar{options}) @ovar{block} +@vindex @code{Debugger.start(options)} +@vindex @code{Debugger.start(block)} +Turn on add additional instrumentation code to facilitate debugging. A +system even table hook is installed and some variables are set up to +access thread frames. + +This needs to be done before entering the debugger; therefore a call +to the debugger issue a @code{Debugger.start} call if necessary. + +If called without a block, @code{Debugger.start} returns @code{true} if +the debugger was already started. But if you want to know if the +debugger has already been started @code{Debugger.started?} can tell +you. + +If a block is given, the debugger is started and @code{yields} to +block. When the block is finished executing, the debugger stopped with +the @code{Debugger.stop method}. You will probably want to put a call +to @code{debugger} somwhere inside that block + +But if you want to completely stop debugger, you must call +@code{Debugger.stop} as many times as you called Debugger.start +method. + +The first time Debugger.start is called there is also some additional +setup to make the @code{restart} command work. In particular, @code{$0} and +@code{ARGV} are used to set internal debugger variables. + +Therefore you should make try to make sure that when +@code{Debugger.start} is called neither of these variables has been +modified. If instead you don't want this behavior you can pass an +options has and set the @code{:init} key to @code{false}. That is +@smallexample + Debugger.start(:init => false) # or Debugger.start(@{:init => false@}) +@end smallexample + +If you want post-mortem debugging, you can also supply +@code{:post_mortem => true} in @code{Debugger.start}. + +@item Debugger.started? +@vindex @code{Debugger.started?} +Boolean. Return @code{true} if debugger has been started. + +@item Debugger.stop +@vindex @code{Debugger.stop} +Turn off instrumentation to allow debugging. Return @code{true} is returned +if the debugger is disabled, otherwise it returns @code{false}. +@emph{Note that if you want to stop debugger, you must call Debugger.stop +as many times as you called the @code{Debugger.start} method.} + +@item Debugger.run_script(@var{debugger-command-file}, out = handler.interface) +@vindex @code{Debugger.run_script} +Reads/runs the given file containing debugger commands. @code{.rdebugrc} is run this way. + +@item Debugger.last_exception +@vindex @code{Debugger.last_exception} +If not @code{nil}, this contains @code{$!} from the last exception. + +@end table + +@node Debugger.context +@subsection @code{Debugger.context} +As mentioned previously, @code{Debugger.start} instruments additional +information to be obtained about the current block/frame stack. Here +we describe these additional @code{Debugger.context} methods. + +Were a frame position is indicated, it is optional. The top or current frame +position (position zero) is used if none is given. + +@table @code +@item Debugger.context.frame_args @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_args} +If track_frame_args? is true, return information saved about call +arguments (if any saved) for the given frame position. + +@item Debugger.context.frame_args_info @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_args_info} + +@item Debugger.context.frame_class @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_args_info} +Return the class of the current frame stack. + +@item Debugger.context.frame_file @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_file} +Return the filename of the location of the indicated frame position. + +@item Debugger.context.frame_id @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_id} +Same as @code{Debugger.context.method}. + +@item Debugger.context.frame_line @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_line} +Return the filename of the location of the indicated frame position. + +@item Debugger.context.frame_method @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_method} +Symbol of the method name of the indicated frame position. + +@item Debugger.context.stack_size +@vindex @code{Debugger.context.stack_size} +Return the number the size of the frame stack. Note this may be less +that the actual frame stack size if debugger recording +(@code{Debugger.start}) was turned on at after some blocks were added +and not finished when the @code{Debugger.start} was issued. +@end table + +@node Debugger.settings +@subsection @code{Debugger.settings} +@vindex @code{Debugger.settings} +Symbols listed here are keys into the Array @code{Debugger.settings}. +These can be set any time after the @code{ruby-debug} is loaded. For example: +@smallexample + require "ruby-debug/debugger" + Debugger.settings[:autoeval] = true # try eval on unknown debugger commands + Debugger.listsize = 20 # Show 20 lines in a list command +@end smallexample + +@table @code +@item :argv +Array of String. @code{argv[0]} is the debugged program name and +@code{argv[1..-1]} are the command arguments to it. +@item :autoeval +Boolean. True if auto autoeval on. @xref{Autoeval}. +@item :autoirb +Fixnum: 1 if on or 0 if off. @xref{Autoirb}. +@item :autolist +Fixnum: 1 if on or 0 if off. +@item :basename +Boolean. True if basename on. @xref{Basename}. +@item :callstyle +Symbol: @code{:short} or @code{:last}. @xref{Callstyle}. +@item :debuggertesting +Boolean. True if currently testing the debugger. +@item :force_stepping +Boolean. True if stepping should go to a line different from the last +step. @xref{Forcestep}. +@item :full_path +Boolean. @xref{Fullpath}. +@item :listsize +Fixnum. Number of lines to show in a @code{list} command. @xref{Listsize}. +@item :reload_source_on_change +Boolean. True if we should reread the source every time it changes. @xref{Autoreload}. +@item :stack_trace_on_error +Boolean. True if we should produce a stack trace on error. @xref{Trace}. +@item :width +Fixnum. Number of characters the debugger thinks are in a line. @xref{Width}. +@end table + +@node Debugger Class +@section The @code{Debugger} Class +@menu +* Debugger.Breakpoint:: Debugger::Breakpoint +* Debugger.Context:: Debugger::Context +* Debugger.Command:: Debugger::Command +@end menu + +@table @code +@item add_breakpoint(file, line, expr) +@vindex @code{Debugger.add_breakpoint} +Adds a breakpoint in file @var{file}, at line @var{line}. If +@var{expr} is not nil, it is evaluated and a breakpoint takes effect +at the indicated position when that expression is true. You should +verify that @var{expr} is syntactically valid or a @code{SyntaxError} +exception, and unless your code handles this the debugged program may +terminate. + +@item remove_breakpoint(bpnum) +@vindex @code{Debugger.remove_breakpoint} +When a breakpoint is added, it is assigned a number as a way to +uniquely identify it. (There can be more than one breakpoint on a +given line.) To remove a breakpoint, use @code{remove_breakpoint} with +breakpoint number @var{bpnum}. + +@item breakpoints +@vindex @code{Debugger.breakpoints} +Return a list of the breakpoints that have been added but not removed. +@end table + +@node Debugger.Breakpoint +@subsection The @code{Debugger::Breakpoint} Class +Breakpoint are objects in the @code{Debugger::Breakpoint} class. +@table @code +@item enabled? +@vindex @code{Debugger::Breakpoints.enabled?} +Returns whether breakpoint is enabled or not. + +@item enabled= +@vindex @code{Debugger::Breakpoints.enabled=} +Sets whether breakpoint is enabled or not. + +@item expr +@vindex @code{Debugger::Breakpoints.expr} +Expression which has to be true at the point where the breakpoint is +set before we stop. + +@item expr= +@vindex @code{Debugger::Breakpoints.expr=} + +@item hit_condition +@item hit_condition= +@vindex @code{Debugger::Breakpoints.condition} +@vindex @code{Debugger::Breakpoints.condition=} + +@item hit_count +@vindex @code{Debugger::Breakpoints.hit_count} +Returns the hit count of the breakpoint. + +@item hit_value +@vindex @code{Debugger::Breakpoints.hit_value} +Returns the hit value of the breakpoint. + +@item hit_value= +@vindex @code{Debugger::Breakpoints.hit_value=} +Sets the hit value of the breakpoint. + +@item id +@cindex @code{Debugger::Breakpoints.id} +A numeric name for the breakpoint which is used in listing breakpoints +and removing, enabling or disabling the breakpoint + +@item pos +@vindex @code{Debugger::Breakpoints.pos=} +Returns the line number of this breakpoint. +@item pos= +@vindex @code{Debugger::Breakpoints.pos=} +Sets the line number of this breakpoint. + +@item source +@vindex @code{Debugger::Breakpoints.source} +Returns the file name in which the breakpoint occurs. + +@item source= +@vindex @code{Debugger::Breakpoints.source=} +Sets the file name in which the breakpoint occurs. +@end table + +@node Debugger.Context +@subsection The @code{Debugger::Context} Class +Callbacks in @code{Debugger:Context} get called when a stopping point +or an event is reached. It has information about the suspended program +which enable a debugger to inspect the frame stack, evaluate variables +from the perspective of the debugged program, and contains information +about the place the debugged program is stopped. + +@table @code +@item at_line(@var{file}, @var{line}) +@vindex Debugger::Context::at_line(@var{file}, @var{line}) +This routine is called when the debugger encounters a ``line'' event for +which it has been indicated we want to stop at, such as by hitting a +breakpoint or by some sort of stepping. + +@item at_return(@var{file}, @var{line}) +@vindex Debugger::Context::at_return(@var{file}, @var{line}) +This routine is called when the debugger encounters a ``return'' event for +which it has been indicated we want to stop at, such as by hitting a +@code{finish} statement. + +@item debug_load(@var{file}, @var{stop-initially}) +@vindex Debugger::Context::debug_load(@var{file}, @var{stop-initially}) +This method should be used to debug a file. If the file terminates +normally, @code{nil} is returned. If not a backtrace is returned. + +The @var{stop-initially} parameter indicates whether the program +should stop after loading. If an explicit call to the debugger is in +the debugged program, you may want to set this @code{false}. +@end table + +@node Debugger.Command +@subsection The @code{Debugger::Command} Class + +Each command you run is in fact its own class. Should you want to extend +ruby-debug, it's pretty easy to do since after all ruby-debug is Ruby. + +Each @code{Debugger#Command} class should have the a @code{regexp} +method. This method returns regular expression for command-line +strings that match your command. It's up to you to make sure this +regular expression doesn't conflict with another one. If it does, it's +undefined which one will get matched and run + +In addition the instance needs these methods: +@table @code +@item execute +Code which gets run when you type a command (string) that matches the +commands regular expression. +@item help +A string which gets displayed when folks as for help on that command +@item help_command +A name used the help system uses to show what commands are available. +@end table + +Here's a small example of a new command: +@smallexample +module Debugger + class MyCommand < Command + def regexp + /^\s*me$/ # Regexp that will match your command + end + + def execute + puts "hi" # What you want to happen when your command runs + end + class << self + def help_command + 'me' # String name of command + end + def help(cmd) + # Some sort of help text. + %@{This does whatever it is I want to do@} + end + end +end +@end smallexample + +Now here's an example of how you can load/use it: +@smallexample + require 'rubygems' + require 'ruby-debug' + require '/tmp/mycmd.rb' # or wherever + Debugger.start + x=1 + debugger + y=2 +@end smallexample + +And now an example of invoking it: +@smallexample +ruby /tmp/testit.rb: +/tmp/testit.rb:7 +y=2 +(rdb:1) help +ruby-debug help v0.10.3 +Type 'help ' for help on a specific command +Available commands: +backtrace delete enable help method putl set trace +break disable eval info next quit show undisplay +catch display exit irb p reload source up +condition down finish list pp restart step var +continue edit frame me ps save thread where + ^^ This is you + +(rdb:1) help me +This does whatever it is I want to do +(rdb:1) me +hi +(rdb:1) +@end smallexample + +@node Kernel routines +@section Additions to @code{Kernel} + +@table @code + +@item debugger @ovar{steps=1} +@vindex @code{Kernel::debugger} +Enters the debugger in the current thread after a stepping @var{steps} line-event steps. +Before entering the debugger startup script is read. + +Setting @var{steps} to 0 will cause a break in the debugger subroutine +and not wait for eany line event to occur. This could be useful you +want to stop right after the last statement in some scope. + +Consider this example: +@smallexample +$ cat scope-test.rb + +require 'rubygems' +require 'ruby-debug' ; Debugger.start +1.times do + a = 1 + debugger # implied steps=1 + end +y = 1 + +$ scope-test.rb:8 +y = 1 +(rdb:1) p a +NameError Exception: undefined local variable or method `a' for main:Object +(rdb:1) +@end smallexample +The debugger will get at the line event which follows @samp{a=1}. This +is outside the @code{do} block scope where @var{a} is defined. If +instead you want to stop before leaving the @code{do} loop it is +possibly to stop right inside the @code{debugger}; call with 0 zero parameter: +@smallexample +$ cat scope-test.rb + +require 'rubygems' +require 'ruby-debug' ; Debugger.start +1.times do + a = 1 + debugger(0) +end +y = 1 + +$ scope-test.rb:8 +../lib/ruby-debug-base.rb:175 +Debugger.current_context.stop_frame = 0 +(rdb:1) where +--> #0 Kernel.debugger(steps#Fixnum) at line ../lib/ruby-debug-base.rb:175 + #1 at line scope-test.rb:6 + #2 at line scope-test.rb:4 +(rdb:1) up +#1 at line scope-test.rb:6 +(rdb:1) p a +1 +(rdb:1) +@end smallexample +As seen above you will have to position the frame up one to be back in +your debugged program rather than in the debugger. + +@item breakpoint @ovar{steps=1} +@vindex @code{Kernel::breakpoint} +An alias for debugger. + +@item binding_n @ovar{n=0} +@vindex @code{Kernel::binding_n} +Returns a @samp{binding()} for the @var{n}-th call frame. Note however +that you need to first call @samp{Debugger.start} before issuing this +call. + +@end table + +@node Using from Subversion +@appendix Building and Installing from rubyforge's Subversion Repository + +Here are Unix-centric instructions. If you have Microsoft Windows or +OSX some of the below may need adjusting. + +@menu +* Prerequisites:: +* Package Checkout:: +* Trying Out:: +* Running Regression Tests:: +* Building the Documentation and Emacs files:: +* Building for Microsoft Windows:: +@end menu + +@node Prerequisites +@section Prerequisites: To build the package you'll need at a minimum: + +@itemize @bullet +@item +Ruby (of course). Currently only version 1.8.6 and above but not +version 1.9.@emph{x} work. +@item +Ruby development headers. This typically includes a file called @file{ruby.h} +@item +A C compiler like GNU C (@code{gcc}) +@item +Rake +@item +Subversion (@code{svn}). +@end itemize + +If you want to build the documentation and install Emacs files, you'll +also need: + +@itemize @bullet +@item + a POSIX shell like bash +@item + autoconf +@item + automake +@item + GNU Make +@item + texinfo +@end itemize + +@node Package Checkout +@section Basic Package Checkout and Installation + +Check out the trunk of repository following the instructions at +@url{http://rubyforge.org/scm/?group_id=1900} For example on a Unixy system, +this may work: + +@smallexample + mkdir ruby-debug + cd ruby-debug + svn checkout svn://rubyforge.org/var/svn/ruby-debug/trunk trunk +@end smallexample + +In order to make the Ruby gems, @code{ruby-debug} and +@code{ruby-debug-base}, get yourself into the trunk directory after +the code has been checked out and run: + +@smallexample + cd trunk # This is the same trunk checked out above. + rake package +@end smallexample + +If all goes well you should have some gem files put in the directory +@code{pkg}. Use the gem command to install that. + +@smallexample + sudo gem install ruby-debug-*.gem # See gem help for other possibilities +@end smallexample + +If all goes well the rdebug script has been installed ruby-debug is +now ready to run. But if everything goes well you might want to run +the built-in regression tests to make sure everything is okay. +See step 3 below. + +If the gem install didn't work,'t there may be a problem with your C +compiler or the Ruby headers are not installed. + +@node Trying Out +@section Trying Out without Installing + +You don't have to build a gem file to try out ruby debug. In fact when +developing new features for ruby-debug, developers often you want to +try it out @emph{before} installing. If you have a problem in the latter +part of step 1 you may want to try this approach since we go into a +little more detail as to what happens under the covers when you do the +gem install. + +Run (from trunk) +@smallexample + rake lib +@end smallexample + +This creates a Makefile and builds the ruby-debug shared library. (On +Unix the name is @code{ruby_debug.so}). + +Once this is done you can run the debugger as you would rdebug using the +script @code{runner.sh}. For example (again from trunk) + +@smallexample + ./runner.sh ~/my-ruby-program.rb +@end smallexample + +@node Running Regression Tests +@section Running the Regression Tests + +We've put together some basic tests to make sure ruby-debug is doing +what we think it should do. To run these (from @code{trunk}): + +@smallexample + rake test +@end smallexample + +If you didn't build the ruby-debug shared library and skipped step 2, +don't worry @code{rake test} will do step 2 for you. You should see a +line that ends something like: + +@smallexample + Finished in 2.767579 seconds. + + 12 tests, 35 assertions, 0 failures, 0 errors +@end smallexample + +The number of seconds, tests, and assertions may be different from the +above. However you @emph{should} see exactly ``0 failures, 0 errors.'' + +@node Building the Documentation and Emacs files +@section Building the Documentation and Testing/Installing Emacs Files + +Of course, I recommend you read the ruby-debug manual that comes with +the package. If you have the prerequisites described above, run this +once: +@smallexample + sh ./autogen.sh +@end smallexample + +Then run: +@smallexample + ./configure + make + make test # Runs Emacs regression tests + sudo make install # Or arrange to do this as root +@end smallexample + +@node Building for Microsoft Windows +@section Building for Microsoft Windows + +Microsoft Windows is ``special'' and building @code{ruby-debug-base} +on it requires extra care. A problem here seems to be that the +``One-click'' install is compiled using Microsoft Visual Studio C, version 6 +which is not sold anymore and is rather old. + +Instead I suggest building via mingw/msys. +@url{http://eigenclass.org/hiki.rb?cmd=view&p=cross+compiling+rcovrt&key=mingw} +has instructions on how to do. Some amendments to these instructions. + +First, those instructions are a little GNU/Linux centric. If you are +using Ubuntu or Debian, then this should be the easiest to follow the +instructions. On Ubuntu or Debian there is a mingw3 Debian +package. Installing that will give you the cross compiler that is a +prerequisite. Alternatively if you are running MS Windows I notice +that cygwin also has a mingw package. Or possibly you could use MinGW +directly. For other OS's you might have to build a cross-compiler, +i.e. gcc which emits win32 code and can create a win32 DLL. + +After you have a cross compiler you need to download the Ruby source +and basically build a ruby interpreter. The cross-compile.sh script +works although when I downloaded it, it had lots of blank space at the +beginning which will mess up the Unix magic interpretation. That is +remove the blanks in front of @code{#/bin/sh}. + +On my system, this script fails in running @code{make ruby} because the +fake.rb that got created needed to have a small change: + +@smallexample + + ALT_SEPARATOR = "\"; \ +@end smallexample +should be: +@smallexample + ALT_SEPARATOR = "\\"; \ +@end smallexample + +After fixing this, run @code{make ruby}. Also, I needed to run +@code{make rubyw}. + +And then @code{make install} as indicated. + +Once all of that's in place, the place you want be is in +@code{ruby-debug/trunk/ext/win32}, not @code{ruby-debug/ext}. + +So let's say you've installed the cross-compiled install ruby in +@code{/usr/local/ruby-mingw32/}. Here then are the commands to build @code{ruby-debug-base-}@emph{xxx}@code{-mswin32.gem}: +@smallexample + cd .../ruby-debug/trunk/ext/win32 + ruby -I /usr/local/ruby-mingw32/lib/ruby/1.8/i386-mingw32 ../extconf.rb + make # Not rake + cd ../.. # back in ruby-debug/trunk + rake win32_gem +@end smallexample + +@node Class Module Index +@unnumbered Class, Module Method Index +@printindex vr + +@node Command Index +@unnumbered Command Index +@printindex ky + +@node General Index +@unnumbered General Index +@printindex cp + +@tex +% I think something like @colophon should be in texinfo. In the +% meantime: +\long\def\colophon{\hbox to0pt{}\vfill +\centerline{The body of this manual is set in} +\centerline{\fontname\tenrm,} +\centerline{with headings in {\bf\fontname\tenbf}} +\centerline{and examples in {\tt\fontname\tentt}.} +\centerline{{\it\fontname\tenit\/},} +\centerline{{\bf\fontname\tenbf}, and} +\centerline{{\sl\fontname\tensl\/}} +\centerline{are used for emphasis.}\vfill} +\page\colophon +% Blame: doc@cygnus.com, 1991. +@end tex + +@bye diff --git a/doc/.svn/text-base/test-tri2.rb.svn-base b/doc/.svn/text-base/test-tri2.rb.svn-base new file mode 100644 index 0000000..2be90bc --- /dev/null +++ b/doc/.svn/text-base/test-tri2.rb.svn-base @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby +require "test/unit" +require "tri2.rb" +require "rubygems" +require "ruby-debug" +Debugger.start + +class TestTri < Test::Unit::TestCase + def test_basic + debugger + solutions = [] + 0.upto(5) do |i| + solutions << triangle(i) + end + assert_equal([0, 1, 3, 6, 10, 15], solutions, + "Testing the first 5 triangle numbers") + end +end diff --git a/doc/.svn/text-base/tri3.rb.svn-base b/doc/.svn/text-base/tri3.rb.svn-base new file mode 100644 index 0000000..0564847 --- /dev/null +++ b/doc/.svn/text-base/tri3.rb.svn-base @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +def triangle(n) + (0..n).inject do |sum, i| + sum +=i + end +end +puts triangle(3) + diff --git a/doc/.svn/text-base/triangle.rb.svn-base b/doc/.svn/text-base/triangle.rb.svn-base new file mode 100644 index 0000000..39f038c --- /dev/null +++ b/doc/.svn/text-base/triangle.rb.svn-base @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +# Compute the n'th triangle number - the hard way +# triangle(n) == (n * (n+1)) / 2 +def triangle(n) + tri = 0 + 0.upto(n) do |i| + tri += i + end + return tri + end + +puts triangle(3) diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..477fc7e --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,63 @@ +############################################################################## +# $Id: Makefile.am,v 1.3 2006/12/28 12:34:25 rockyb Exp $ +# Copyright (C) 2007 Rocky Bernstein +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## + +EXT=1 +man1_MANS = rdebug.$(EXT) + +EXTRA_DIST = $(man1_MANS) \ + hanoi.rb primes.rb test-tri2.rb tri3.rb triangle.rb \ + ruby-debug.info ruby-debug.html ruby-debug.pdf + +info_TEXINFOS = ruby-debug.texi rdebug-emacs.texi + +all: $(INFO_DEPS) $(man1_MANS) html pdf + +pdf: ruby-debug.pdf rdebug-emacs.pdf + +txt: ruby-debug.txt rdebug-emacs.txt + +ps: ruby-debug.ps rdebug-emacs.ps + +man: $(man1_MANS) + +html: ruby-debug.html rdebug-emacs.html + +ruby-debug.html: ruby-debug.texi + texi2html $(srcdir)/ruby-debug.texi || true + +rdebug-emacs.html: rdebug-emacs.texi + texi2html $(srcdir)/rdebug-emacs.texi || true + +%.ps.gz: %.ps + gzip -9c $< > $@ + +# Our `texinfo.tex' must reside in the current directory, otherwise +# texi2dvi will use the default. +.texi.pdf: + $(TEXI2PDF) -I $(srcdir) $< + +.texi.dvi: + $(TEXI2DVI) -I $(srcdir) $< + +.dvi.ps: + test -d $(docdir) || mkdir $(docdir) + $(DVIPS) $< -o $@ + +all-formats: pdf dvi txt ps html + +MOSTLYCLEANFILES = rubydb.tgs rubydb.ps.gz rubydb.pdf rubydb.html rubydb_toc.html rubydb_foot.html rubydb-man.html diff --git a/doc/emacs-notes.txt b/doc/emacs-notes.txt new file mode 100644 index 0000000..4568791 --- /dev/null +++ b/doc/emacs-notes.txt @@ -0,0 +1,38 @@ +* rdebug.el is loaded by the user when Emacs is launched. (Should +Rdebug ever be part of Emacs, this should be the items autoloaded by +Emacs.) + +There is a command buffer which is the gud process. There are a number +of "secondary" buffers have in gud-comint-buffer the gud process. The +way we go the other direction from gud process to secondary buffer is +by buffer name. Source buffers don't seem to have a local +gud-comint-buffer variable set but use the global value. Perhaps +source buffer should have their own buffer-local value(s)? + +For each secondary buffer we have things for that specific buffer. In particular: +* frames (rdebug-frames.el) +* output (rdebug-output.el) +* variables (rdebug-varbuf.el) +* watch or display-expressions - (rdebug-watch.el +* breakpoints (rdebug-breaks.el) + +Each specific secondary buffer includes + - setting the buffer up, + - specific commands for that buffer + - the kinds of functions that buffer deals with (e.g. frame + things for the "frame" buffer or breakpoints for the "breakpoints" buffer.) + +* rdebug-gud.el contains things that interface to gdb. Possibly also +things that interface to gdb-ui should be there as well. + +* rdebug-shortkey.el has all the magic that needs to be done to make + shortkey mode work. + +* rdebug-track is all the things to make rdebug-track mode work. + +I have some additions, which deals with *when* certain files are loaded. + +* rdebug-source.el is loaded when the first Ruby source file is loaded +Of course, the name rdebug-source.el is not important, we could rename +it to something else and reuse the name for other source-related +things. diff --git a/doc/hanoi.rb b/doc/hanoi.rb new file mode 100644 index 0000000..99c4c10 --- /dev/null +++ b/doc/hanoi.rb @@ -0,0 +1,35 @@ +#!/usr/bin/ruby + +def hanoi(n,a,b,c) + if n-1 > 0 + hanoi(n-1, a, c, b) + end + puts "Move disk %s to %s" % [a, b] + if n-1 > 0 + hanoi(n-1, c, b, a) + end +end + +i_args=ARGV.length +if i_args > 1 + puts "*** Need number of disks or no parameter" + exit 1 +end + +n=3 + +if i_args > 0 + begin + n = ARGV[0].to_i + rescue ValueError, msg: + print "** Expecting an integer, got: %s" % ARGV[0].to_s + exit 2 + end +end + +if n < 1 or n > 100 + puts "*** number of disks should be between 1 and 100" + exit 2 +end + +hanoi(n, :a, :b, :c) diff --git a/doc/primes.rb b/doc/primes.rb new file mode 100644 index 0000000..e94219c --- /dev/null +++ b/doc/primes.rb @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby +# Enumerator for primes +class SievePrime + @@odd_primes = [] + def self.next_prime(&block) + candidate = 2 + yield candidate + not_prime = false + candidate += 1 + while true do + @@odd_primes.each do |p| + not_prime = (0 == (candidate % p)) + break if not_prime + end + unless not_prime + @@odd_primes << candidate + yield candidate + end + candidate += 2 + end + end +end +SievePrime.next_prime do |prime| + puts prime + break if prime > 10 +end + + diff --git a/doc/rdebug-emacs.texi b/doc/rdebug-emacs.texi new file mode 100644 index 0000000..89a5cab --- /dev/null +++ b/doc/rdebug-emacs.texi @@ -0,0 +1,1030 @@ +\input texinfo @c -*-texinfo-*- +@setfilename rdebug-emacs.info + +@set DBG ruby-debug +@set ttrdebug @code{rdebug} +@set ttDBG @code{@value{DBG}} +@set Emacs @sc{gnu} Emacs + +@set RDEBUG_EMACS_VERSION 0.1 +@include version-rdebug-emacs.texi +@finalout + +@c Karl Berry informs me that this will add straight quotes in +@c typewriter text. +@c See the "Inserting Quote Characters" node in the Texinfo manual +@set txicodequoteundirected +@set txicodequotebacktick + +@c THIS MANUAL REQUIRES TEXINFO 4.0 OR LATER. + +@c This is a dir.info fragment to support semi-automated addition of +@c manuals to an info tree. +@dircategory Programming & development tools. +@direntry +* ruby-debug-emacs: (ruby-debug). Ruby Debugger for GNU Emacs +@end direntry + +@titlepage +@title Debugging with @code{ruby-debug} inside GNU Emacs Version @value{RDEBUG_EMACS_VERSION} +@sp 1 +@subtitle @value{EDITION} Edition +@subtitle @value{UPDATED-MONTH} +@author Rocky Bernstein and Anders Lindgren +@page +@ifset WHERETO +@tex +{\parskip=0pt +\hfill (Send bugs and comments on ruby-debug to fill in...)\par +\hfill {\it Debugging with {\tt ruby-debug}\par +\hfill \TeX{}info \texinfoversion\par +} +@end tex +@end ifset +@end titlepage +@page + +@node Top, Getting started, (dir), (dir) +@top Debugging with ruby-debug under GNU Emacs + +@menu +* Getting started:: +* The Multi-window Mode:: +* Debugger Buffers:: +* Emacs Debugger Commands:: Indexes (nodes containing large menus) +* Emacs Command Index:: An item for each GNU/Emacs command name. +* Emacs Function Index:: An item for each Emacs Function. +* Emacs Key Binding Index:: An item for each Emacs Debugger Command. + +@detailmenu + --- The Detailed Node Listing --- + +Getting started + +* Installation:: How to install this package +* Emacs rdebug:: Invoke the ruby debugger initially +* Emacs shell tracking mode:: Entering rdebug from an existing shell buffer + +Debugger Buffers + +* Debugger Command Buffer:: +* Emacs Source:: Commands from the source script + +Emacs Debugger Commands + +* Emacs Debugger Common Commands:: +* Emacs Debugger Breakpoint Buffer Commands:: +* Emacs Debugger Stack Buffer Commands:: +* Emacs Debugger Variable Buffer Commands:: +* Emacs Debugger Watch Buffer Commands:: +* Emacs GUD Commands:: + +@end detailmenu +@end menu + +This file describes ruby-debug, the Ruby Debugger, +version @value{RDEBUG_EMACS_VERSION} + +This is the @value{EDITION} Edition, @value{UPDATED} +@c Copyright (C) 2007 ... + +@c @node GNU Emacs +@c @chapter Using @code{ruby-debug} from GNU Emacs + + +@cindex @value{Emacs} +A special interface which comes with Ruby that allows you to use +@value{Emacs} to view (and edit) the source files for the program you +are debugging with @value{DBG}. However you must be using at least +version 21 of @value{Emacs}, but with @value{Emacs} version 22 or 23 +there are even more debugging features available. @code{M-x +show-emacs-version} inside @value{Emacs} will tell you what version you +are running. + +This package provide a full-fledged debugging environment, on par with +modern integrated development environments. Once the debugger has been +activated, the Emacs frame is divided into a number of dedicated +debugger windows.@footnote{If you are an @value{Emacs} traditionalist, +you can, of course, run this package with only a shell and source +buffer} + +This package comes with a number of predefined window layouts. It is +fully customizable so you can create your own. + +@c ------------------------------------------------------------------- + + +@node Getting started, The Multi-window Mode, Top, Top +@chapter Getting started + +@menu +* Installation:: How to install this package +* Emacs rdebug:: Invoke the ruby debugger initially +* Emacs shell tracking mode:: Entering rdebug from an existing shell buffer +* Configurating this package:: Introducing the configure system +@end menu + +@node Installation, Emacs rdebug, Getting started, Getting started +@section Installation + +To use this interface, load the file @code{rdebug.el}. This file is a +light-weight file, basically it only contains a handful of +@code{autoload} directives. + +For example, you can place the following in your @code{~/.emacs} file: + +@smallexample + (require 'rdebug) +@end smallexample + +In addition, you must have Ruby and ruby-debug installed. + + +@node Emacs rdebug, Emacs shell tracking mode, Installation, Getting started +@section Emacs rdebug + +Use the command @kbd{M-x rdebug} in @sc{gnu} Emacs to start debugging. +Give the executable file you want to debug as an argument. Make sure +to use the version that comes with this package as this is newer than +that supplied with @value{Emacs}. + +The @kbd{rdebug} command starts @value{DBG} as a subprocess of Emacs, +with input and output through a newly created Emacs buffer. + +Using @value{DBG} under Emacs is just like using @value{DBG} +normally except for two things: + +@itemize @bullet +@item +All ``terminal'' input and output goes through the GNU Emacs buffer. +@end itemize + +This applies both to @value{DBG} commands and their output, and to the input +and output done by the program you are debugging. + +This is useful because it means that you can copy the text of previous +commands and input them again; you can even use parts of the output +in this way. + +All the facilities of GNU Emacs' Shell mode are available for interacting +with your script. In particular, you can send signals the usual +way---for example, @kbd{C-c C-c} for an interrupt, @kbd{C-c C-z} for a +stop. + +@node Emacs shell tracking mode, Configurating this package, Emacs rdebug, Getting started +@section Entering rdebug from an existing shell buffer + +Many times it's not feasible to enter the debugger from the outset. +Instead a call to the debugger is put inside the program. + +@c See @xref{Unit Testing Session}. + +It is also possible in GNU emacs to use a (``comint'') shell and set a +mode to watch for @value{DBG} prompts and track the source code in +another window. @xref{Interactive Shell, , Shell, Emacs, The @value{Emacs} +Manual}. + +To enable, this run @kbd{M-x turn-on-rdebug-track-mode}. There is some +overhead involved in scanning output, so if you are not debugging Ruby +programs you probably want to turn this off which can be done via the +@code{M-x turn-off-rdebugtrack} command. + + +@node Configurating this package, , Emacs shell tracking mode, Getting started +@section Configurating this package + +In this manual we present a number of @value{Emacs} lisp variables and +functions that you can use to configure the debugger interface. In +addition, you can use the @value{Emacs} @emph{customize} system, see the +@kbd{ } menu item. + +@c ------------------------------------------------------------------- + +@node The Multi-window Mode, Debugger Buffers, Getting started, Top +@chapter Multi-window + +In the multi-window debugger mode, a number of buffers are visible when +the debugger starts. This chapter will describe each of them, in +addition it will describe the features associated with the multi-window +mode. + +The default multi-window layout looks like the following: + +@verbatim ++----------------------------------------------------------------------+ +| Toolbar | ++-----------------------------------+----------------------------------+ +| | | +| Debugger shell | Variables buffer | +| | | ++-----------------------------------+----------------------------------+ +| | | +| Source buffer | Output buffer | +| | | ++-----------------------------------+----------------------------------+ +| | | +| Stack buffer | Breakpoints buffer | +| | | ++-----------------------------------+----------------------------------+ +@end verbatim + +@section Activating Multi-window mode + +The variable @code{rdebug-many-windows} controls if multi-window mode +should be used, it is enabled by default. When starting the debugger +using the @code{M-x rdebug} mode the command line option @code{--emacs +3} must be specified (this is also the default). + +When attaching to an already running debugger process, you must give the +debugger command @kbd{set annotate 3}. + +@section Window Layouts + +When the debugger is started, the original window layout of +@value{Emacs} is replaced with the window layout of the debugger. You +can switch back and forth between the original window layout and the +debugger layout using +@kbd{M-x rdebug-display-original-window-configuration} and +@kbd{M-x rdebug-display-debugger-window-configuration}. + +If, for some reason, the debugger layout has been garbled you can +restore it to the original state using @kbd{M-x +rdebug-restore-debugger-window-layout}. + +The debugger provides a number of different window layouts. The easies +way to try them out is to use the menu @kbd{ +} and select any in the section starting with @code{Standard}. + + +@section The buffers + +All buffers in this section share a set of commands for common debugger +operations and for switching between buffers. In addition, each buffer +has got a set of dedicated commands. + +All debugger buffers, with the exception of source and the debugger +shell window, are called @emph{secondary buffers}. + +@subsection Keybindings for all Debugger Windows + +The debugger provides key-bindings that work in all debugger windows, +including Ruby source buffers. The key bindings are designed to match +keys of commonly used debugger environments. + +The variable @code{rdebug-populate-common-keys-function} can be assigned +to a function that should bind the keys use. Three functions are +provided @code{rdebug-populate-common-keys-standard}, +@code{...-eclipse}, and @code{...-netbeans}. + +@multitable @columnfractions 0.4 0.2 0.2 0.2 +@headitem Command @tab Standard @tab Eclipse @tab Netbeans +@item Run @tab f5 @tab @tab +@item Quit @tab S-f5 @tab @tab +@item Toggle Breakpoint @tab f9 @tab @tab +@item Enable/Disable Breakpoint @tab C-f9 @tab S-C-b @tab S-f8 +@item Step over @tab f10 @tab f6 @tab f8 +@item Step into @tab f11 @tab f5 @tab f7 +@item Step out @tab S-f11 @tab f7 @tab M-S-f7 + +@end multitable + + + +@subsection Keybindings for Secondary Buffers + +The following commands are available in all secondary windows. + +Capital letters move between secondary buffers as mentioned above (jump +to if visible or replace a secondary if not). + +@table @kbd +@item SPACE +step (edebug compatible) +@item < +Up in the stack trace +@item > +Down in the stack trace +@item ? +Help +@item B +Display breakpoints buffer +@item C +Display command buffer +@item O +Display program output +@item S +Display source window +@item T +Display stack trace buffer +@item V +display variables buffer +@item W +display watch buffer +@item b +Set breakpoint +@item c +Continue (i.e. run) +@item d +Remove breakpoint +@item f +Finish (i.e. step out of the current function) +@item n +Next (i.e. step into function) +@item p +print +@item q +Quit +@item r +Restart +@item s +Step (i.e. step over function) +@end table + +You can use the same commands in the source buffer if you enable +@code{rdebug-short-key-mode}. The best way to do this is to add the +following to your init file: + +@smallexample + (add-hook 'rdebug-mode-hook 'rdebug-turn-on-short-key-mode) +@end smallexample + + + +@subsection The Debugger Shell Buffer + +The @emph{debugger shell window} is the main communication channel +between @value{DBG} and @value{Emacs}. You can use the shell to issue +debugger commands directly. In addition, any @value{Emacs} debugger +command you issue will be translated into shell commands, and the output +will be parsed. + +It is the ambition that the @value{Emacs} debugger interface should be +in a state where the debugger shell window would not need to be visible. + +@subsection The Source Buffer + +The @emph{source buffers} (or buffers) contains the actual Ruby source +code that is being debugged. A small arrow in the left fringe displays +the current line. Active breakpoints are displayed as red dots and +passive as grey. + +@subsection The Output Buffer + +The @emph{output buffer} displays any output the debugged program emits. + +The option @code{rdebug-use-separate-io-buffer} controls if the output +buffer should be used, or if the output would go into the debugger shell +buffer. + +@subsection The Variables Buffer + +In this buffer, local and object variables are displayed. The values of +the variables can be edited. + +@table @kbd +@item RET +Edit the value +@item e +Print the value +@item x +Pretty-print the value +@end table + +@subsection The Stack Trace Buffer + +The @emph{stack trace} buffer displays the function that is currently +being debugger, the function that called it, etc., all the way up to the +originally called function. + +You can navigate in the stack trace buffer in order to see the source of +any function in the call chain. The Variables buffer will also be +updated to reflect the local variables of that function. + +@table @kbd +@item RET +Select a function to display +@item +Go to a stack frame +@end table + +@subsection The Watch Buffer + +The @emph{Watch Buffer} can display arbitrary expressions, including, +but not limited to, global variables. + +@table @kbd +@item a +Add a watch expression +@item C-d, d +Delete a watch expression +@item RET, e +Edit a watch expression +@item +Go to the expression +@end table + +@subsection The Breakpoints Buffer + +The @emph{Breakpoints Buffer} displays all breakpoints that currently are +defined and shows if they are enabled or disabled. + +@table @kbd +@item t +Toggle a breakpoint between enabled and disabled +@item i +Add a breakpoint condition +@item ret +Goto a breakpoint +@item C-d +Delete a breakpoint +@item +Go to the expression +@end table + +@subsection The Help Buffer + +The @emph{Help Buffer} is displayed whenever you press @code{?}. It will +display a help text on the available debugger commands and commands to +navigate between the buffers. + + +@c ------------------------------------------------------------------- + +@node Debugger Buffers, Emacs Debugger Commands, The Multi-window Mode, Top +@chapter Debugger Buffers + +@menu +* Debugger Command Buffer:: +* Emacs Source:: Commands from the source script +@end menu + +@node Debugger Command Buffer, Emacs Source, Debugger Buffers, Debugger Buffers +@section Emacs Debugger Command buffer + +Each time @value{DBG} displays a stack frame, Emacs automatically finds the +source file for that frame and puts an arrow (@samp{=>}) at the +left margin of the current line. Emacs uses a separate buffer for +source display, and splits the screen to show both your @value{DBG} session +and the source. + +Explicit @value{DBG} @code{list} or search commands still produce output as +usual, but you probably have no reason to use them from GNU Emacs. + +@quotation +@emph{Warning:} If the directory where your script resides is not your +current directory, it can be easy to confuse Emacs about the location of +the source files, in which case the auxiliary display buffer does not +appear to show your source. @value{DBG} can find programs by searching your +environment's @code{PATH} variable, so the @value{DBG} input and output +session proceeds normally; but Emacs does not get enough information +back from @value{DBG} to locate the source files in this situation. To +avoid this problem, either start @value{DBG} mode from the directory where +your script resides, or specify an absolute file name when prompted for the +@kbd{M-x gdb} argument. + +A similar confusion can result if you use the @value{DBG} @code{file} command to +switch to debugging a program in some other location, from an existing +@value{DBG} buffer in Emacs. +@end quotation + +@noindent +(preceded by @kbd{M-:} or @kbd{ESC :}, or typed in the @code{*scratch*} buffer, or +in your @file{.emacs} file). + +In the @value{DBG} I/O buffer, you can use the Emacs commands listed +below in addition to the standard Shell mode commands. The I/O buffer +name name is usually @code{*gud-}@emph{script-name}@code{*}, where +@emph{script-name} is the name of the script you are debugging. + +Many of the commands listed below are also bound to a second key +sequence which also can be used in the also be used in the source +script. These are listed in @ref{Emacs Source}. + +In secondary buffers many commands are available the corresponding +final keystroke. For example @code{C-c n} in a secondary buffer is +@code{n}. + +@table @kbd +@item C-h m +Describe the features of Emacs' @value{DBG} Mode. + +@item C-x C-a C-b (gud-break) +@pindex C-x C-a C-b (gud-break) +Set breakpoint at current line. + +@item C-x C-a C-d (gud-remove) +@pindex C-x C-a C-d (gud-remove) +Remove breakpoint at current line. + +@item C-x C-a C-l (gud-refresh) +@pindex C-x C-a C-d (gud-refresh) +Fix up a possibly garbled display, and redraw the arrow. + +@item C-c RET (comint-copy-old-input) +@pindex C-c RET (comint-copy-old-input) +Insert after prompt old input at point as new input to be edited. +Calls `comint-get-old-input' to get old input. + +@item C-c n (gud-next) +@pindex C-c n (gud-next) +Step one line, skipping functions. (Step over). + +@item C-x C-a C-o (comint-delete-output) +@pindex C-c n (comint-delete-output) +Delete all output from interpreter since last input. Does not delete +the prompt. + +@item C-x C-a C-r (gud-cont) + +@item C-c SPC (gud-step @var{arg}) +@pindex C-c SPC (gud-step @var{arg}) +@itemx C-x C-a C-s (gud-step @var{arg}) +@pindex C-x C-a C-s (gud-step @var{arg}) +Step one source line. Same as @value{DBG} @code{step} command. The +@value{Emacs} command name is @code{gud-step} and @code{C-x C-a C-s} +is an alternate binding which can be used in the source +script. +@c @xref{Step}. + +With a numeric argument, run that many times. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + + +@item C-x C-a C-t (gud-tbreak @var{arg}) +Set temporary breakpoint at current line. + +@item C-x C-a C-w (backward-kill-word) +@item C-x C-a C-x (comint-get-next-from-history) +@item C-x C-a C-z (comint-stop-subjob) +Stop the current subjob. +This command also kills the pending input +between the process mark and point. + +WARNING: if there is no current subjob, you can end up suspending +the top-level process running in the buffer. If you accidentally do +this, use M-x comint-continue-subjob to resume the process. (This +is not a problem with most shells, since they ignore this signal.) + +@item C-x C-a C-\ (comint-quit-subjob) +Send quit signal to the current subjob. +This command also kills the pending input +between the process mark and point. + +@item C-c + (gud-step-plus) +Run @code{step+}. + +@item C-c . (comint-insert-previous-argument @var{index}) +Insert the @emph{index-th} argument from the previous Comint command-line at point. +Spaces are added at beginning and/or end of the inserted string if +necessary to ensure that it's separated from adjacent arguments. +Interactively, if no prefix argument is given, the last argument is inserted. +Repeated interactive invocations will cycle through the same argument +from progressively earlier commands (using the value of index specified +with the first command). + +@item C-c < (gud-up) +Go up a stack frame. With a numeric argument, go up that many +stack frames. Same @value{DBG} @code{up} command. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + +@item C-c > (gud-down) +Go down a stack frame. Same as @value{DBG} @code{down}. +With a numeric argument, go down that many stack frames. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + +@item C-c ? (rdebug-display-secondary-window-help-buffer) +Display the rdebug help buffer. + +@item C-c B (rdebug-display-breakpoints-buffer) +Display the rdebug breakpoints buffer. + +@item C-x C-a C (rdebug-display-cmd-buffer) +Display the rdebug command buffer. + +@item C-c O (rdebug-display-output-buffer) +Display the rdebug output buffer. + +@item C-c R (gud-run) +@itemx C-c r (gud run) +Restart or run the script. Same as @value{DBG} @code{run} command. + +@item C-c S (gud-source-resync) +@item C-c T (rdebug-display-stack-buffer) +Display the rdebug stack buffer. +@item C-c V (rdebug-display-variables-buffer) +Display the rdebug variables buffer. + +@item C-c W (rdebug-display-watch-buffer) +Display the rdebug watch buffer. + +@item C-c f (gud-finish @var{arg}) +@pindex C-c f (gud-finish @var{arg}) +Finish executing current function. + +@itemx C-x C-a C-f (gud-finish) +@pindex C-x C-a C-f (gud-finish) +Finish executing current function. The same as @value{DBG} +@code{finish} command. +@c @xref{Finish}. + +@item C-c n (gud-next) +@pindex C-c n (gud-next) +Execute to next source line in this function, skipping all function +calls. Same as @value{DBG} @code{next} command. +@c @xref{Next}. + +With a numeric argument, run that many times. +@c @xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} Manual}. + +@item C-c q (gud-quit) + +@item C-x C-a C-l +Resynchronize the current position with the source window. The +@value{Emacs} command name is @code{gud-refresh} and @code{C-x C-a +C-l} is an alternate binding which also can be used in the source script. + +@item C-c a +Shows argument variables (e.g.@: @code{$1}, @code{$2}) of the current +stack frame. Same as @value{DBG} @code{info args} command. The +@value{Emacs} command name is @code{gud-args} and @code{C-x C-a a} is +an alternate binding which also can be used in the source script. + +@item C-c T +Show stack trace. Same as @value{DBG} @code{where} command. The +@value{Emacs} command name is @code{gud-where} and @code{C-x C-a T} is +an alternate binding which can be used in the source +script. +@c @xref{Backtrace}. + +@end table + +In any source file, the Emacs command @kbd{C-x SPC} (@code{gud-break}) +tells @value{DBG} to set a breakpoint on the source line point is on. + +If you accidentally delete the source-display buffer, an easy way to get +it back is to type the command @code{frame} in the @value{DBG} buffer, to +request a frame display; when you run under Emacs, this recreates +the source buffer if necessary to show you the context of the current +frame. + +The source files displayed in Emacs are in ordinary Emacs buffers +which are visiting the source files in the usual way. You can edit +the files with these buffers if you wish; but keep in mind that @value{DBG} +communicates with Emacs in terms of line numbers. If you add or +delete lines from the text, the line numbers that @value{DBG} knows cease +to correspond properly with the code. + +@xref{Debugger Operation, , , Emacs, The @value{Emacs} +Manual}. + +@node Emacs Source, , Debugger Command Buffer, Debugger Buffers +@section Commands from the source script + +@table @kbd +@item C-x SPC + +tells @value{DBG} to set a breakpoint on the source +line point is on. (@code{gud-break}) + +@item C-x C-a t + +@code{gud-linetrace} + +@item C-x C-a C-f +Restart or run the script. Same as @value{DBG} @code{run} command. The +@value{Emacs} command name is @code{gud-finish}. In the corresponding +I/O buffer, @code{C-c R} is an alternate binding. + +@item C-x C-a T +Show stack trace. Same as @value{DBG} @code{where} command. In the +corresponding I/O buffer, @code{C-c T} is an alternate +binding. +@c @xref{Backtrace}. + +@item C-x C-a < + +Go up a stack frame. With a numeric argument, go up that many +stack frames. Same @value{DBG} @code{up} command. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} Manual}. + +The @value{Emacs} command name is @code{gud-up}. In the corresponding +I/O buffer, @code{C-c <} is an alternate binding. + +@item C-x C-a > + +Go down a stack frame. Same as @value{DBG} @code{down}. +With a numeric argument, go down that many stack frames. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + +The @value{Emacs} command name is @code{gud-down}. In the +corresponding I/O buffer, @code{C-c >} is an alternate binding. + +@item C-x C-a C-t + +@code{gud-tbreak} + +@item C-x C-a C-s + +Step one source line. Same as @value{DBG} @code{step} +command. +@c @xref{Step}. + +With a numeric argument, run that many times. +@xref{Arguments, , Numeric Arguments, Emacs, The @value{Emacs} +Manual}. + +The @value{Emacs} command name is @code{gud-step}. In the +corresponding I/O buffer, @code{C-x C-a C-s} is an alternate binding. + +@item C-x C-a C-e + +@code{gud-statement} + +@item C-x C-a R +Restart or run the script. Same as @value{DBG} @code{run} command. The +@value{Emacs} command name is @code{gud-run}. In the corresponding I/O +buffer, @code{C-c R} is an alternate binding. + +@item C-x C-a C-d +Delete breakpoint. @code{gud-remove} + +@item C-x C-a C-p + +@code{gud-print} + +@item C-x C-a C-n + +Execute to next source line in this function, skipping all function +calls. Same as @value{DBG} @code{next} command. With a numeric +argument, run that many times. @xref{Arguments, , Numeric Arguments, +Emacs, The @value{Emacs} Manual}. + +The @value{Emacs} command name is @code{gud-next}. In the +corresponding I/O buffer, @code{C-x C-a C-n} is an alternate binding. + +@item C-x C-a f C-f + +@code{gud-finish} + +@item C-x C-a C-r +Continue execution of your script Same as @value{DBG} @code{continue} +command. The @value{Emacs} command name is @code{gud-cont}. In the +corresponding I/O buffer, @code{C-x C-a C-r} is an alternate binding. +@c See @ref{Continue}. + +@item C-x C-a C-b + +@code{gud-break} + +@item C-x C-a a + +@code{gud-args} +Shows argument variables (e.g.@: @code{$1}, @code{$2}) of the current +stack frame. Same as @value{DBG} @code{info args} command. The +@value{Emacs} command name is @code{gud-args}. In the corresponding +I/O buffer, @code{C-c a} is an alternate binding which also can be +used in the source script. + +@item C-x C-a C-l +Move to current position in this source window. The @value{Emacs} +command name is @code{gud-refresh}. In the corresponding I/O buffer, +@code{C-x C-a C-l} is an alternate binding. + +@end table + +@node Emacs Debugger Commands, Emacs Command Index, Debugger Buffers, Top +@chapter Emacs Debugger Commands + +@menu +* Emacs Debugger Common Commands:: +* Emacs Debugger Breakpoint Buffer Commands:: +* Emacs Debugger Stack Buffer Commands:: +* Emacs Debugger Variable Buffer Commands:: +* Emacs Debugger Watch Buffer Commands:: +* Emacs GUD Commands:: +@end menu + +@node Emacs Debugger Common Commands, Emacs Debugger Breakpoint Buffer Commands, Emacs Debugger Commands, Emacs Debugger Commands +@section Emacs Debugger Common Commands + +The commands in this section are used to make a secondary buffer +visible. If the buffer doesn't exist, nothing is done. +The way the buffer is made visible is follows the following +rules tried in order: + +@enumerate +@item +If the buffer doesn't exist, do nothing. +@item +If the buffer is already displayed, switch to it. +@item +If the current buffer is a +secondary buffer, bury it replacing with the requested +buffer. +@item +If there is secondary buffer visible, that +is replaced instead. +@item +Just pick a visible buffer to bury and replace. + @end enumerate + +The commands are also have key bindings that end in an uppercase +letter. This letter is given in parenthesis. When in one of the +secondary buffers, the uppercase letter is bound to the command as well. + +@table @kbd + +@item (rdebug-display-breakpoints-buffer) (@kbd{B}) +@findex rdebug-display-breakpoints-buffer (@kbd{B}) +Display the rdebug breakpoints buffer. Bound to: @kbd{C-x C-a B}, +@kbd{ }. Secondary buffers: +@kbd{O}. + +@item (rdebug-display-cmd-buffer) (@kbd{C}) +@findex rdebug-display-cmd-buffer (@kbd{C}) +Display the debugger command buffer. + +Bound to: @kbd{C-x C-a C}, @kbd{ }. + +@item (rdebug-display-output-buffer) (@kbd{O}) +@findex rdebug-display-output-buffer (@kbd{?}) +Display the debugger output buffer. + +Bound to: @kbd{C-x C-a O}, @kbd{ +}. Secondary buffers: @kbd{O}. + +@item (rdebug-display-secondary-window-help-buffer) (@kbd{?}) +@findex rdebug-display-secondary-window-help-buffer (@kbd{?}) + +@item (rdebug-display-stack-buffer) (@kbd{T}) +@findex rdebug-display-stack-buffer (@kbd{T}) +Display the debugger stack buffer. Bound to: @kbd{C-x C-a T}, +@kbd{ }. Secondary buffers: @kbd{T}. + +@item (rdebug-display-variables-buffer) (@kbd{V}) +@findex rdebug-display-variables-buffer (@kbd{V}) +Display the debugger variables buffer. Bound to: @kbd{C-x C-a V}, +@kbd{ }. Secondary buffers: +@kbd{V}. + +@item (rdebug-display-watch-buffer) (@kbd{W}) +@findex rdebug-display-watch-buffer (@kbd{W}) +Display the debugger variables buffer. Bound to: @kbd{C-x C-a W}, +@kbd{ }. Secondary buffers: @kbd{V}. + +@item (rdebug-display-debugger-window-configuration) +@findex rdebug-display-debugger-window-configuration +Display the current layout of windows of the rdebug Ruby debugger. +@item (rdebug-display-original-window-configuration) +@findex rdebug-display-original-window-configuration +Display the layout of windows prior to starting the rdebug Ruby +debugger. This function is called upon quitting the debugger and +@var{rdebug-many-windows} is not nil. +@item (rdebug-goto-entry-n) +@findex rdebug-goto-entry-n +Breakpoints, Display expressions and Stack Frames all have +numbers associated with them which are distinct from line +numbers. In a secondary buffer, this function is usually bound to +a numeric key. which will position you at that entry number. To +go to an entry above 9, just keep entering the number. For +example, if you press 1 and then 9, you should jump to entry +1 (if it exists) and then 19 (if that exists). Entering any +non-digit will start entry number from the beginning again. +@item (rdebug-quit) - q +@findex rdebug-quit (q) +Kill the debugger process associated with the buffer. + +When @var{rdebug-many-windows} is active, the original window layout is +restored. +@item (rdebug-restore-windows) +@findex rdebug-restore-windows +Display the initial ruby debugger window layout. + +@end table + + +@node Emacs Debugger Breakpoint Buffer Commands, Emacs Debugger Stack Buffer Commands, Emacs Debugger Common Commands, Emacs Debugger Commands +@section Emacs Debugger Breakpoint Buffer Commands + +@table @kbd +@item (rdebug-goto-breakpoint) +@findex rdebug-goto-breakpoint +@item (rdebug-goto-breakpoint-mouse) +@findex rdebug-goto-breakpoint-mouse +@item (rdebug-breakpoints-mode) +@findex rdebug-breakpoints-mode +Major mode for displaying breakpoints in a secondary window. Uses +@var{rdebug-breakpoints-mode-map}. +@end table + +@node Emacs Debugger Stack Buffer Commands, Emacs Debugger Variable Buffer Commands, Emacs Debugger Breakpoint Buffer Commands, Emacs Debugger Commands +@section Emacs Debugger Stack Buffer Commands + +@table @kbd +@item (rdebug-goto-stack-frame) +@findex rdebug-goto-stack-frame +@item (rdebug-frames-mode) +@findex rdebug-frames-mode +Major mode for displaying the stack trace. Uses +@var{rdebug-frames-mode-map}. +@end table + +@node Emacs Debugger Variable Buffer Commands, Emacs Debugger Watch Buffer Commands, Emacs Debugger Stack Buffer Commands, Emacs Debugger Commands +@section Emacs Debugger Variable Buffer Commands + +@table @kbd +@item (rdebug-variables-edit) +@findex rdebug-variables-edit +@end table + +@node Emacs Debugger Watch Buffer Commands, Emacs GUD Commands, Emacs Debugger Variable Buffer Commands, Emacs Debugger Commands +@section Emacs Debugger Watch Buffer Commands + +@table @kbd +@item (rdebug-watch-add) +@findex rdebug-watch-add +Add a display expression. +@item (rdebug-watch-delete) +@findex rdebug-watch-delete +Delete a display expression. +@item (rdebug-watch-edit) +@findex rdebug-watch-edit +Edit a display expression. +@item (rdebug-watch-mode) +@findex rdebug-watch-mode +Major mode for displaying the display expressions. Uses +@var{rdebug-watch-mode-map}. +@end table + +@node Emacs GUD Commands, , Emacs Debugger Watch Buffer Commands, Emacs Debugger Commands +@section Emacs Debugger GUD Commands + +@table @kbd +@item (comint-copy-old-input) +@findex comint-copy-old-input +Insert after prompt old input at point as new input to be edited. +Calls `comint-get-old-input' to get old input. +@item (comint-delete-output) +@findex comint-delete-output +Delete all output from interpreter since last input. +Does not delete the prompt. +@item (gud-break) +@findex gud-break +Set a breakpoint on the source line point is on. +@item (gud-cont) - c +@findex gud-cont (c) +Continue execution. +@item (gud-next) - n +@findex gud-next (n) +Step one line, skipping functions. (Step over). +@item (gud-refresh) +@findex gud-refresh +Fix up a possibly garbled display, and redraw the arrow. +@item (gud-remove) +@findex gud-remove +Remove breakpoint at current line. +@item (gud-step) - s +@findex gud-step (s) +Step one statement. (Step into) +@item (gud-step-plus) - + +@findex gud-step-plus (+) +Run @code{step+}---like @code{gud-step} but ensure we go to a new +line. +@item (gud-tbreak @var{arg}) +@findex gud-tbreak +Set temporary breakpoint at current line. +@end table + +@node Emacs Command Index, Emacs Function Index, Emacs Debugger Commands, Top +@unnumbered Emacs Command Index +@printindex pg + +@node Emacs Function Index, Emacs Key Binding Index, Emacs Command Index, Top +@unnumbered Emacs Function Index +@printindex fn + +@node Emacs Key Binding Index, , Emacs Function Index, Top +@unnumbered Key Binding Index +@printindex ky + +@tex +% I think something like @colophon should be in texinfo. In the +% meantime: +\long\def\colophon{\hbox to0pt{}\vfill +\centerline{The body of this manual is set in} +\centerline{\fontname\tenrm,} +\centerline{with headings in {\bf\fontname\tenbf}} +\centerline{and examples in {\tt\fontname\tentt}.} +\centerline{{\it\fontname\tenit\/},} +\centerline{{\bf\fontname\tenbf}, and} +\centerline{{\sl\fontname\tensl\/}} +\centerline{are used for emphasis.}\vfill} +\page\colophon +% Blame: doc@cygnus.com, 1991. +@end tex + +@bye diff --git a/doc/rdebug.1 b/doc/rdebug.1 new file mode 100644 index 0000000..81241cf --- /dev/null +++ b/doc/rdebug.1 @@ -0,0 +1,241 @@ +.\" $Id: rdebug.1 516 2007-12-31 05:55:24Z rockyb $ +.TH rdebug 1 +.SH NAME +rdebug \- Fast Ruby debugger +.SH SYNOPSIS +.B rdebug +[debugger-options] +rdebug +[script-options...] +.SH "DESCRIPTION" +This manual page documents briefly the +.BR rdebug +command. +.PP +.B rdebug +is a fast implementation of the standard Ruby debugger debug.rb. It +is implemented by utilizing a Ruby C API hook, allows for remote +debugging and can be used as the Ruby debugger backend interface for a +development environment. +.PP +The commands generally follow gdb's command set unless there's good +reason not to. + +.PP +rdebug can do four main kinds of things (plus other things in support of +these) to help you catch bugs in the act: + +.TP +\ \ \ \(bu +Start or restart your Ruby script, specifying arguments that might +affect its behavior. + +.TP +\ \ \ \(bu +Make your program stop at various points possibly determined by +specified conditions. + +.TP +\ \ \ \(bu +Examine what has happened when your program has stopped. + +.TP +\ \ \ \(bu +Change things in your program, so you can experiment with correcting the +effects of one bug and go on to learn about another. +.PP + +Here are some of the most frequently-needed commands: +.TP +.B break \fR[\|\fIfile\fB:\fIline\fR\fR|\fIclass.method\fR] \fR[if \fIexpr\fR] +\& +Set a breakpoint at \c +.I class.method\c +\& or at the specified file and line. +.TP +.B continue \fR[\fIline\fR] +Continue running your program (after stopping, e.g. at a +breakpoint). If a line is given a one-time breakpoint is set there. +.TP +.B delete \fR[\fIbreakpoint-numbers\fR] +\& +Delete breakpoints by number. If no number is given delete all breakpoints. +.TP +.B down \fR[\|\fIcount\fR\|] +Move down one block frame. If count is given move up that many frames. A negative number +goes the other direction and is like the up command +.TP +.B finish +Run until the completion of the current function or method. +.TP +.BI frame " frame-number" +Set the stack frame to \fIframe-number\fR for purposes of examinine local variables. For positioning relative to the current frame, use +.B up +or +.B down. A negative number starts counting from the other end. +.TP +.B help \fR[\|\fIname\fR\|] +Show information about rdebug command \c +.I name\c +\&, or general information +about using rdebug. +.TP +.B info \fR[\|\fIname\fR\|] +Get the various information usually about the debugged program. +.TP +.B irb \fIcommand\fR +Run an interactive ruby shell (irb) using the current environment. +.TP +.B list \fR[\|\fIfile\fB:\fIline\fR|\fIfunction] +type the text of the program in the vicinity of where it is presently stopped +or at the specified function or file and line. +.TP +.B next \fR[\|\fIcount\fR\|] +Execute next program line(s) (after stopping); step \c +.I over\c +\& any +function calls in the line. +.TP +.BI pp " expr"\c +\& +Pretty print the value of an expression. +.TP +.BI print " expr"\c +\& +Display the value of an expression. +.TP +.BI ps " expr"\c +\& +Print an array as a columized sorted list. +.TP +.B quit +Exit from the debugger. +.TP +.B run \fR[\|\fIarglist\fR\|] +(Re)start your program (with \c +.I arglist\c +\&, if specified). If you want the debugger to get reloaded, use +.B restart +instead. +.TP +.B set +Modify parts of the debugger environment. +.TP +.B show +See the debugger environment settings +.TP +.BI source " filename"\c +\& +Read and execute the lines in file \fIfilename\fR as a series of debugger +commands. +.TP +.B step \fR[\|\fIcount\fR\|] +Execute next program line(s) (after stopping); step \c +.I into\c +\& any +function calls in the line. +.TP +.B up \fR[\|\fIcount\fR\|] +Move up one block frame. If count is given move up that many frames. A negative number +goes the other direction and is like the down command +.TP +.B where \fR[\|\fIcount\fR\|] +Display all or \fIcount\fR items of the program stack. +.PP +For full details on rdebug, see \c +http://rubyforge.org/projects/ruby-debug/ +.SH OPTIONS +.PP +.TP 10 +.TP +.B \-A | \-\-annotate LEVEL +Set gdb-style annotation to LEVEL, a number. Additional information is output +automatically when program state is changed. This can be used by +front-ends such as GNU Emacs to post this updated information without +having to poll for it. +.TP +.B \-\-client +Connect to a remote debugger. Used with another rdebug invocation using \-\-server. +See also \-\-host and \-\-cport options +.TP +.B \-\-cport=PORT +Port used for control commands. +.TP +.B \-d | \-\-debug +Set $DEBUG true. +.TP +.B \-\-emacs +Activates full GNU Emacs mode. Is the equivalent of setting the +options \-\-emacs\-basic, \-\-annotate=3, \-\-no-stop, \-\-no\-control +and \-\-post\-mortem. +.TP +.B \-\-emacs-basic +Activates GNU Emacs mode. Debugger prompts are prefaced with two octal +032 characters. +.TP +.B \-h | \-\-host=HOST +Host name used for remote debugging. +.TP +.B \-I | \-\-include PATH +Add PATH to $LOAD_PATH +.TP +.B \-m | \-\-post-mortem +Activate post-mortem mode. +.TP +.B \-\-no-control +Do not automatically start control thread. +.TP +.B \-\-no\-stop +Do not stop when script is loaded. +.TP +.B \-p | \-\-port=PORT +Host name used for remote debugging. +.TP +.B \-r | \-\-require SCRIPT +Require the library, before executing your script. +.TP +.B \-\-script FILE +Name of the script file to run. +.TP +.B \-x | \-\-trace +Show lines before executing them. +.TP +.B \-\-no\-quit +Do not quit when script terminates. Instead rerun the program. +.TP +.B \-\-version +Show the version number and exit. +.TP +.B \-\-verbose +Turn on verbose mode. +.TP +.B \-\-v +Print the version number, then turn on verbose mode if a script name +is given. If no script name is given just exit after printing the +version number. +.TP +.B \-\-nx +Don't execute commands found in any initialization files, e.g. .rdebugrc. +.TP +.B \-\-keep-frame-binding +Keep frame bindings. +.TP +.B \-\-script=FILE +Name of the script file to run +.B \-s | \-\-server +Listen for remote connections. Another rdebug session accesses using the \-\-client option. +See also the \-\-host, \-\-port and +\-\-cport options +.TP +.B \-w | \-\-wait +Wait for a client connection, implies -s option. +.TP +.B \-\-help +Show invocation help and exit. +.PD +.SH "SEE ALSO" +.Sp +http://rubyforge.org/projects/ruby-debug/ +.SH AUTHOR +rdebug was written by Kent Siblev. This manual page was written by +Rocky Bernstein diff --git a/doc/ruby-debug.texi b/doc/ruby-debug.texi new file mode 100644 index 0000000..c50ae37 --- /dev/null +++ b/doc/ruby-debug.texi @@ -0,0 +1,3982 @@ +\input texinfo @c -*-texinfo-*- +@setfilename ruby-debug.info + +@set DBG ruby-debug +@set ttrdebug @code{rdebug} +@set ttDBG @code{@value{DBG}} +@set Emacs @sc{gnu} Emacs + +@c Karl Berry informs me that this will add straight quotes in +@c typewriter text. +@c See the "Inserting Quote Characters" node in the Texinfo manual +@set txicodequoteundirected +@set txicodequotebacktick +@set RDEBUG_VERSION 0.10.4 + +@macro Example {} +@iftex +@cartouche +@end iftex +@smallexample +@end macro + +@macro EndExample {} +@iftex +@end cartouche +@end iftex +@end smallexample +@end macro + +@macro DBG {} +@value{DBG} +@end macro + +@macro ttDBG {} +@value{ttrdebug} +@end macro + +@c How to show optional variables. +@macro ovar{varname} +@r{[}@var{\varname\}@r{]} +@end macro + +@settitle ruby-debug +@setchapternewpage odd +@c %**end of header + +@include version.texi + +@finalout + +@c THIS MANUAL REQUIRES TEXINFO 4.0 OR LATER. + +@c This is a dir.info fragment to support semi-automated addition of +@c manuals to an info tree. +@dircategory Programming & development tools. +@direntry +* ruby-debug: (ruby-debug). Ruby Debugger +@end direntry + +@titlepage +@title Debugging with @code{ruby-debug} +@sp 1 +@subtitle @value{EDITION} Edition +@subtitle @value{UPDATED-MONTH} +@author Rocky Bernstein and Kent Sibilev +@page +@ifset WHERETO +@tex +{\parskip=0pt +\hfill (Send bugs and comments on ruby-debug to fill in...)\par +\hfill {\it Debugging with {\tt ruby-debug}\par +\hfill \TeX{}info \texinfoversion\par +} +@end tex +@end ifset +@end titlepage +@page + +@ifnottex +@node Top, Summary, (dir), (dir) +@top Debugging with ruby-debug + +This file describes ruby-debug, the Ruby Debugger, +version @value{RDEBUG_VERSION} + +This is the @value{EDITION} Edition, @value{UPDATED} +@c Copyright (C) 2007 ... + +@menu +* Summary:: Overview of Debugger with sample sessions +* Invocation:: Getting in and out +* Debugger Command Reference:: rdebug command reference +* Post-Mortem Debugging:: Debugging on an uncaught exception +* Debugger Module and Class:: ruby-debug's Debugger module and class + +Appendix +* Using from Subversion:: + +Indexes (nodes containing large menus) +* Class Module Index:: An item for Class, Module, and Methods. +* Command Index:: An item for each command name. +* General Index:: An item for each concept. +@end menu + +@end ifnottex + +@contents + +@node Summary +@chapter Summary of @code{ruby-debug} + +The purpose of a debugger such as @DBG{} is to allow you to see what is +going on ``inside'' a Ruby program while it executes. + +@ttDBG{} can do four main kinds of things (plus other things in support of +these) to help you catch bugs in the act: + +@itemize @bullet +@item +Start your script, specifying anything that might affect its behavior. + +@item +Make your script stop on specified conditions. + +@item +Examine what has happened, when your script has stopped. + +@item +Change things in your script, so you can experiment with correcting the +effects of one bug and go on to learn about another. +@end itemize + +Although you can use @value{ttrdebug} to invoke your Ruby programs via +a debugger at the outset, there are other ways to use and enter the +debugger. + +@menu +* First Sample Session:: A Simple Sample @code{rdebug} session +* Second Sample Session:: Second Session Delving a little deeper @code{rdebug} session +* Unit Testing Session:: Using the debugger in unit testing +* Debugger.start with a block:: Using the Debugger.start with a block +* Debugging Oddities:: How debugging Ruby may be different... +@end menu + +@node First Sample Session +@section The First Sample @code{rdebug} Session (@code{list}, @code{display}, @code{print}, and @code{quit}) + +You can use this manual at your leisure to read all about @value{ttDBG}. +However, a handful of commands are enough to get started using the +debugger. The following sections illustrates these commands. + +@iftex +In this sample session, we emphasize user input like this: @b{input}, +to make it easier to pick out from the surrounding output. +@end iftex + +Below is Ruby code to compute a triangle number of a given +length.@footnote{There are of course shorter ways to define @code{triangle} +such as: +@smallexample + def triangle(n) (n * (n+1)) / 2 end +@end smallexample +The code we use in this example and the next is more for pedagogical +purposes than how to write short Ruby code.} + + +@smallexample +$ @b{rdebug triangle.rb} +triangle.rb:4 def hanoi(n,a,b,c) +(rdb:1) @b{list} +[-1, 8] in ./triangle.rb + 1 #!/usr/bin/env ruby + 2 # Compute the n'th triangle number - the hard way + 3 # triangle(n) == (n * (n+1)) / 2 +=> 4 def triangle(n) + 5 tri = 0 + 6 0.upto(n) do |i| + 7 tri += i + 8 end +(rdb:1) @b{l} +[9, 18] in ./triangle.rb + 9 return tri + 10 end + 11 + 12 puts triangle(3) +(rdb:1) @b{list 1,100} +[1, 100] in ./triangle.rb + 1 #!/usr/bin/env ruby + 2 # Compute the n'th triangle number - the hard way + 3 # triangle(n) == (n * (n+1)) / 2 +=> 4 def triangle(n) + 5 tri = 0 + 6 0.upto(n) do |i| + 7 tri += i + 8 end + 9 return tri + 10 end + 11 + 12 puts triangle(3) +(rdb:1) +@end smallexample + +@noindent + +There are lots of command options, but we don't need them for now. See +@ref{rdebug command-line options} for a full list of command options. + +Position information consists of a filename and line number, +e.g.@: @code{triangle.rb:4}. We are currently stopped before the first +executable line of the program; this is line 4 of +@code{triangle.rb}. If you are used to less dynamic languages and have +used debuggers for more statically compiled languages like C, C++, or +Java, it may seem odd to be stopped before a function definition. But +in Ruby line 4 is executed, the name @code{triangle} (probably) does +not exist so issuing a method call of @code{triangle} will raise a +``method not found'' error. + +@DBG{}'s prompt is @code{(rdb:@emph{n})}. The @emph{n} is the thread +number. Here it is 1 which is usually the case for the main thread. If +the program has died and you are in post-mortem debugging, there is no +thread number. In this situation, the string @code{post-mortem} is +used in place of a thread number. If the program has terminated +normally, the string this position will be @code{ctrl}. The commands +which are available change depending on the program state. + +The first command, @code{list} (@pxref{List}), prints 10 lines +centered around the current line; the current line here is line 4 and +is marked by @code{=>}, so the range the debugger would like to show +is -1..8. However since there aren't 5 lines before the current line, +those additional lines---``lines'' -1 and 0---are dropped and we print +the remaining 8 lines. The @code{list} command can be abbreviated +with @code{l} which is what we use next. Notice that when we use this +a second time, we continue listing from the place we last left +off. The desired range of lines this time is lines 9 to 18; but since +the program ends as line 12, only the remaining 4 lines are shown. + +If you want to set how many lines to print by default rather than use +the initial number of lines, 10, use the @code{set listsize} command +(@pxref{Listsize}). To see the entire program in one shot, we gave an +explicit starting and ending line number. + +If you use a front-end to the debugger such as the Emacs interface, +@c (@pxref{GNU Emacs}) +you probably won't use @code{list} all that much. + +Now let us step through the program. + +@smallexample +(rdb:1) @b{step} +triangle.rb:12 +puts triangle(3) +(rdb:1) @b{@key{}} +triangle.rb:5 +tri = 0 +(rdb:1) @b{p tri} +nil +(rdb:1) @b{step} +triangle.rb:6 +0.upto(n) do |i| +(rdb:1) @b{p tri} +0 +@end smallexample + +The first @kbd{step} command (@pxref{Step}) runs the script one +executable unit. The second command we entered was just hitting the +return key; @ttDBG{} remembers the last command you entered was +@code{step}, so it runs that last command again. + +One way to print the values of variables uses @code{p}. (Of course, +there are of course lots of other ways too.). When we look at the +value of @code{tri} the first time, we see it is @code{nil}. Again we +are stopped @emph{before} the assignment on line 5, and this variable +hasn't been set previously. However after issuing another ``step'' +command we see that the value is 0 as expected. You could issue the +step and print comman in one shot: + +However if every time we stop we want to see the value of @code{tri} +to see how things are going stop, there is a better way by setting a +display expression (@pxref{DisplayCommands}). + +@smallexample +(rdb:1) display tri +1: tri = 0 +@end smallexample + +Now let us run the program until we return from the function. However +we'll want to see which lines get run. + +@smallexample +(rdb:1) @b{display i} +2: i = +(rdb:1) @b{set linetrace on} +line tracing is on. +(rdb:1) @b{finish} +Tracing(1):triangle.rb:7 tri += i +1: tri = 0 +2: i = 0 +Tracing(1):triangle.rb:7 tri += i +1: tri = 0 +2: i = 1 +Tracing(1):triangle.rb:7 tri += i +1: tri = 1 +2: i = 2 +Tracing(1):triangle.rb:7 tri += i +1: tri = 3 +2: i = 3 +Tracing(1):triangle.rb:9 return tri +1: tri = 6 +2: i = +(rdb:1) @b{quit} +Really quit? (y/n) y +@end smallexample + +So far, so good. A you can see from the above to get out of the +debugger, one can issue a @code{quit} command. (@code{q} and +@code{exit} are just as good. If you want to quit without being +prompted, suffix the command with an exclamation mark, e.g.\@code{q!}. + +@node Second Sample Session +@section Sample Session 2: Delving Deeper (@code{where}, @code{frame}, @code{restart}, @code{autoeval}, @code{break}, @code{ps}) + +In this section we'll introduce breakpoints, the call stack and +restarting. So far we've been doing pretty good in that we've not +encountered a bug to fix. Let's try another simple example. Okay +here's the program. + +Below we will debug a simple Ruby program to solve the classic Towers +of Hanoi puzzle. It is augmented by the bane of programming: some +command-parameter processing with error checking. + +@smallexample +$ @b{rdebug hanoi.rb} +hanoi.rb:3 def hanoi(n,a,b,c) +(rdb:1) @b{list 1,100} +[1, 100] in ./hanoi.rb + 1 #!/usr/bin/ruby + 2 +=> 3 def hanoi(n,a,b,c) + 4 if n-1 > 0 + 5 hanoi(n-1, a, c, b) + 6 end + 7 puts "Move disk %s to %s" % [a, b] + 8 if n-1 > 0 + 9 hanoi(n-1, c, b, a) + 10 end + 11 end + 12 + 13 i_args=ARGV.length + 14 if i_args > 1 + 15 puts "*** Need number of disks or no parameter" + 16 exit 1 + 17 end + 18 + 19 n=3 + 20 + 21 if i_args > 0 + 22 begin + 23 n = ARGV[0].to_i + 24 rescue ValueError, msg: + 25 print "** Expecting an integer, got: %s" % ARGV[0].to_s + 26 exit 2 + 27 end + 28 end + 29 + 30 if n < 1 or n > 100 + 31 puts "*** number of disks should be between 1 and 100" + 32 exit 2 + 33 end + 34 + 35 hanoi(n, :a, :b, :c) +(rdb:1) +@end smallexample + +Recall in the first section I said that before the @code{def} is run +the method it names is undefined. Let's check that out. First let's +see what private methods we can call before running @code{def hanoi} + +@smallexample +(rdb:1) @b{set autoeval on} +autoeval is on. +(rdb:1) @b{private_methods} +["select", "URI", "local_variables", "lambda", "chomp", ... +@end smallexample + +The @code{set autoeval} (@pxref{Autoeval}) command causes any commands +that are not normally understood to be debugger commands to get +evaluated as though they were Ruby commands. I use this a lot, so I +set this by putting it the command file @code{.rdebugrc}, +@pxref{Command Files}, that gets read when @code{ruby-debug} starts. + +As showing the list output of @code{private_methods}, I find this kind +of list unwieldy. What you are supposed to notice here is that +method @code{hanoi} is not in this list. When you ask +@code{ruby-debug} for a list of method names via @code{method +instance}, it doesn't show output in this way; @code{ruby-debug} can +sort and put into columns lists like this using the print command, @code{ps}. + + +@smallexample +(rdb:1) @b{ps private_methods} +Array exit! puts warn +Float fail raise y +Integer fork rand +Rational format readline +String gem_original_require readlines +URI getc remove_instance_variable +` gets scan +abort global_variables select +active_gem_with_options gsub set_trace_func +at_exit gsub! singleton_method_added +autoload initialize singleton_method_removed +autoload? initialize_copy singleton_method_undefined +binding iterator? sleep +block_given? lambda split +callcc load sprintf +caller local_variables srand +catch location_of_caller sub +chomp loop sub! +chomp! method_missing syscall +chop open system +chop! p test +dbg_print pp throw +dbg_puts print timeout +eval printf trace_var +exec proc trap +exit putc untrace_var +@end smallexample + +Now let's see what happens after stepping + +@smallexample +(rdb:1) @b{private.methods.member?("hanoi")} +false +(rdb:1) @b{step} +hanoi.rb:13 +i_args=ARGV.length +(rdb:1) @b{private_methods.member?("hanoi")} +true +(rdb:1) +@end smallexample + +Okay, now where were we? + +@smallexample +(rdb:1) @b{list} +[8, 17] in ./hanoi.rb + 8 if n-1 > 0 + 9 hanoi(n-1, c, b, a) + 10 end + 11 end + 12 +=> 13 i_args=ARGV.length + 14 if i_args > 1 + 15 puts "*** Need number of disks or no parameter" + 16 exit 1 + 17 end +(rdb:1) @b{ARGV} +[] +@end smallexample + +Ooops. We forgot to specify any parameters to this program. Let's try +again. We can use the @code{restart} command here. + +@smallexample +(rdb:1) @b{restart 3} +Re exec'ing: + /usr/bin/rdebug hanoi.rb 3 +hanoi.rb:3 +def hanoi(n,a,b,c) +(rdb:1) @b{break 4} +Breakpoint 1 file hanoi.rb, line 4 +(rdb:1) @b{continue} +Breakpoint 1 at hanoi.rb:4 +./hanoi.rb:4 if n-1 > 0 +(rdb:1) @b{display n} +1: n = 3 +(rdb:1) @b{display a} +2: a = a +(rdb:1) @b{undisplay 2} +(rdb:1) @b{display a.inspect} +3: a.inspect = :a +(rdb:1) @b{display b.inspect} +4: b.inspect = :b +(rdb:1) @b{continue} +Breakpoint 1 at hanoi.rb:4 +./hanoi.rb:4 +if n-1 > 0 +1: n = 2 +3: a.inspect = :a +4: b.inspect = :c +(rdb:1) @b{c} +Breakpoint 1 at hanoi.rb:4 +./hanoi.rb:4 +if n-1 > 0 +1: n = 1 +3: a.inspect = :a +4: b.inspect = :b +(rdb:1) @b{where} +--> #0 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:4 + #1 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5 + #2 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5 + #3 at line hanoi.rb:35 +(rdb:1) +@end smallexample + +In the above we added a new command, @code{break} +(@pxref{Breakpoints}) which indicates to go into the debugger just +before that line of code is run. And @code{continue} resumes +execution. Notice the difference between @code{display a} and +@code{display a.inspect}. An implied string conversion is performed on +the expression after it is evaluated. To remove a display expression +we used @code{undisplay} is used. If we give a display number, just +that display expression is removed. + +Above we also used a new command @code{where} (@pxref{Backtrace} to +show the call stack. In the above situation, starting from the bottom +line we see we called the hanoi from line 35 of the file +@code{hanoi.rb} and the hanoi method called itself two more times at +line 5. + +In the call stack we show the file line position in the same format +when we stop at a line. Also we see the names of the parameters and +the types that those parameters @emph{currently} have. It's possible +that when the program was called the parameter had a different type, +since the types of variables can change dynamically. You alter the +style of what to show in the trace (@pxref{Callstyle}). + +Let's explore a little more. Now were were we? + +@smallexample +(rdb:1) @b{list} + 1 #!/usr/bin/ruby + 2 + 3 def hanoi(n,a,b,c) +=> 4 if n-1 > 0 + 5 hanoi(n-1, a, c, b) + 6 end + 7 puts "Move disk %s to %s" % [a, b] + 8 if n-1 > 0 +(rdb:1) @b{undisplay} +Clear all expressions? (y/n) @b{y} +(rdb:1) @b{i_args} +NameError Exception: undefined local variable or method `i_args' for main:Object +(rdb:1) @b{frame -1} +#3 at line hanoi.rb:35 +(rdb:1) @b{i_args} +1 +(rdb:1) @b{p n} +3 +(rdb:1) @b{down 2} +#2 Object.-(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at line hanoi.rb:5 +(rdb:1) @b{p n} +2 +@end smallexample + +Notice in the above to get the value of variable @code{n}, I have to +use a print command like @code{p n}; If I entered just @code{n}, that +would be taken to mean the debugger command ``next''. In the current +scope, variable @code{i_args} is not defined. However I can change to +the top-most frame by using the @code{frame} command. Just as with +arrays, -1 means the last one. Alternatively using frame number 3 +would have been the same thing; so would issuing @code{up 3}. + +Note that in the outside frame 3, the value of @code{i_args} can be +shown. Also note that the value of variable @code{n} is different. + +@node Unit Testing Session +@section Using the debugger in unit testing (@code{ruby-debug/debugger}, @code{Debugger.start}) + +In the previous sessions we've been calling the debugger right at the +outset. I confess that this mode of operation is usually not how I use +the debugger. + +There are a number of situations where calling the debugger at the outset is +impractical for a couple of reasons. + +@enumerate +@item +The debugger just doesn't work when run at the outset. By necessity +any debugging changes to the behavior or the program in slight and +subtle ways, and sometimes this can hinder finding the bugs. +@item +There's a lot of code which that needs to get run before the part you +want to inspect. Running this code takes time and you don't the +overhead of the debugger in this first part. +@end enumerate + +In this section we'll delve show how to enter the code in the middle +of your program, while delving more into the debugger operation. + +In this section we will also use unit testing. Using unit tests will +greatly reduce the amount of debugging needed while at the same time +increase the quality of your program. + +What we'll do is take the @code{triangle} code from the first session +and write a unit test for that. In a sense we did write a mini-test +for the program which was basically the last line where we printed the +value of triangle(3). This test however wasn't automated: the +implication is that someone would look at the output and verify that +what was printed is what was expected. + +And before we can turn that into something that can be +@code{required}, we probably want to remove that output. However I +like to keep in that line so that when I look at the file, I have an +example of how to run it. Therefore we will conditionally run this +line if that file is invoked directly, but skip it if it is +not.@footnote{@code{rdebug} resets @code{$0} to try to make things +like this work.} +@smallexample + if __FILE__ == $0 + puts triangle(3) + end +@end smallexample + +Let's call this file @code{tri2.rb}. + +Okay, we're now ready to write our unit test. We'll use +@code{"test/unit"} which comes with the standard Ruby distribution. +Here's the test code: + +@smallexample + #!/usr/bin/env ruby + require 'test/unit' + require 'tri2.rb' + + class TestTri < Test::Unit::TestCase + def test_basic + solutions = [] + 0.upto(5) do |i| + solutions << triangle(i) + end + assert_equal([0, 1, 3, 6, 10, 15], solutions, + 'Testing the first 5 triangle numbers') + end + end +@end smallexample + +If you run it will work. However if you run @code{rdebug} initially, +you will not get into the test, because @code{test/unit} wants to be +the main program. So here is a situation where one may need to modify +the program to add an explicit @emph{entry} into the +debugger.@footnote{For some versions of rake and @code{rdebug} you can +in fact set a breakpoint after running @code{rdebug} +initially. Personally though I find it much simpler and more reliable +to modify the code as shown here.} + +One way to do this is to add the following before the place you want +to stop: +@smallexample + require 'rubygems' + require 'ruby-debug/debugger' +@end smallexample +The line @code{require "rubygems"} is needed if @code{ruby-debug} is +installed as a Ruby gem. + +Let's add this code just after entering @code{test_basic}: +@smallexample + ... + def test_basic + @b{require "rubygems"} + @b{require "ruby-debug/debugger"} + solutions = [] + ... +@end smallexample + +Now we run the program.. +@smallexample + $ @b{ruby test-tri.rb} + Loaded suite test-tri + Started + test-tri.rb:9 + solutions = [] + (rdb:1) +@end smallexample +and we see that we are stopped at line 9 just before the +initialization of the list @code{solutions}. + +Now let's see where we are... + +@smallexample +(rdb:1) @b{where} +--> #0 TestTri.test_basic at line /home/rocky/ruby/test-tri.rb:9 +(rdb:1) +@end smallexample + +Something seems wrong here; @code{TestTri.test_basic} indicates that +we are in class @code{TestTri} in method @code{test_basic}. However we +don't see the call to this like we did in the last example when we +used the @code{where} command. This is because the debugger really +didn't spring into existence until after we already entered that +method, and Ruby doesn't keep call stack information around in a +way that will give the information we show when running @code{where}. + +If we want call stack information, we have to turn call-stack tracking +on @emph{beforehand}. This is done by adding @code{Debugger.start}. + +Here's what our test program looks like so after we modify it to start +tracking calls from the outset + +@smallexample +#!/usr/bin/env ruby +require 'test/unit' +require 'tri2.rb' +require 'rubygems' +@b{Debugger.start} + +class TestTri < Test::Unit::TestCase + def test_basic + @b{debugger} + solutions = [] + 0.upto(5) do |i| + solutions << triangle(i) + end + assert_equal([0, 1, 3, 6, 10, 15], solutions, + "Testing the first 5 triangle numbers") + end +end +@end smallexample + +Now when we run this: +@smallexample +$ @b{ruby test-tri2.rb} +Loaded suite test-tri2 +Started +test-tri2.rb:11 +solutions = [] +(rdb:1) @b{where} +--> #0 TestTri.test_basic at line test-tri2.rb:11 + #1 Kernel.__send__(result#Test::Unit::TestResult) + at line /usr/lib/ruby/1.8/test/unit/testcase.rb:70 + #2 Test::Unit::TestCase.run(result#Test::Unit::TestResult) + at line /usr/lib/ruby/1.8/test/unit/testcase.rb:70 +... + #11 Test::Unit::AutoRunner.run + at line /usr/lib/ruby/1.8/test/unit/autorunner.rb:200 + #12 Test::Unit::AutoRunner.run(force_standalone#FalseClass, ... + at line /usr/lib/ruby/1.8/test/unit/autorunner.rb:13 + #13 at line /usr/lib/ruby/1.8/test/unit.rb:285 +(rdb:1) +@end smallexample + +Much better. But again let me emphasize that the parameter types are +those of the corresponding variables that @emph{currently} exist, and +this might have changed since the time when the call was made. Even so +and even though we only have @emph{types} listed, it's a pretty good +bet that when @code{Test::Unit} was first called, shown above as frame +12, that the values of its two parameters were @code{false} and +@code{nil}. + +@node Debugger.start with a block +@section Using the @code{Debugger.start} with a block + +We saw that @code{Debugger.start()} and @code{Debugger.stop()} allow +fine-grain control over where the debugger tracking should occur. + +Rather than use an explicit @code{stop()}, you can also pass a block +to the @code{start()} method. This causes @code{start()} to run and +then @code{yield} to that block. When the block is finished, +@code{stop()} is run. In other words, this wraps a +@code{Debugger.start()} and @code{Debugger.stop()} around the block of +code. But it also has a side benefit of ensuring that in the presence +of an uncaught exception @code{stop} is run, without having to +explicitly use @code{begin} ... @code{ensure Debugger.stop() end}. + +For example, in Ruby Rails you might want to debug code in one of the +controllers without causing any slowdown to any other code. And +this can be done by wrapping the controller in a @code{start()} with a +block; when the method wrapped this way finishes the debugger is +turned off, and the application proceeds at regular speed. + +Of course, inside the block you will probably want to enter the +debugger using @code{Debugger.debugger()}, otherwise there would +little point in using the @code{start}. For example, you can do this +in @code{irb}: + +@smallexample +$ @b{irb} +irb(main):001:0> @b{require 'rubygems'; require 'ruby-debug'} +=> true +irb(main):002:0> @b{def foo} +irb(main):003:1> @b{x=1} +irb(main):004:1> @b{puts 'foo'} +irb(main):005:1> @b{end} +=> nil +irb(main):006:0> @b{Debugger.start@{debugger; foo@}} +(irb):6 +(rdb:1) @b{s} +(irb):3 +(rdb:1) @b{p x} +nil +(rdb:1) @b{s} +(irb):4 +(rdb:1) @b{p x} +1 +(rdb:1) @b{s} +foo +=> true +irb(main):007:0> +@end smallexample + +There is a counter inside of @code{Debugger.start} method to make sure +that this works when another @code{Debugger.start} method is called +inside of outer one. However if you are stopped inside the debugger, +issuing another @code{debugger} call will not have any effect even if +it is nested inside another @code{Debugger.start}. + +@node Debugging Oddities +@section How debugging Ruby may be different than debugging other Languages + +If you are used to debugging in other languages like C, C++, Perl, +Java or even Bash@footnote{this is just an excuse to put in a +shameless plug for my bash debugger @url{http://bashdb.sf.net}}, there +may be a number of things that seem or feel a little bit different and +may confuse you. A number of these things aren't oddities of the +debugger per see, so much as a difference in how Ruby works compared to +those other languages. Because Ruby works a little differently from +those other languages, writing a debugger has to also be a little +different as well if it is to be useful. + +In this respect, using the debugger may help you understand Ruby +better. + +We've already seen two examples of such differences. One difference is +the fact that we stop on method definitions or @code{def}'s and that's +because these are in fact executable statements. In other compiled +languages this would not happen because that's already been done when +you compile the program (or in Perl when it scans in the program). The +other difference we saw was in our inability to show call stack parameter +types without having made arrangements for the debugger to track +this. In other languages call stack information is usually available +without asking assistance of the debugger.@footnote{However in C, and +C++ generally you have to ask the compiler to add such information.} + +In this section we'll consider some other things that might throw +off new users to Ruby who are familiar with other languages and +debugging in them. + +@menu +* Stack Shows Scope Nesting:: +* More Frequent Evaluations per Line:: +* Bouncing Around in Blocks (e.g. Iterators):: +* No Parameter Values in a Call Stack:: +* Lines You Can Stop At:: +@end menu + +@node Stack Shows Scope Nesting +@subsection Stack Shows Scope Nesting +In a backtrace, you will find more stack frames than you might in say +C. + +Consider another way to write the triangle program of @pxref{First +Sample Session}. + +@smallexample + 1 #!/usr/bin/env ruby + 2 def triangle(n) + 3 (0..n).inject do |sum, i| + 4 sum +=i + 5 end + 6 end + 7 puts triangle(3) +@end smallexample + +Let's stop inside the @code{inject} block: + +@smallexample +$ @b{rdebug tri3.rb} +(rdb:1) @b{c 4} +tri3.rb:4 +sum +=i +(rdb:1) @b{where} +--> #0 Range.triangle at line tri3.rb:4 + #1 Enumerable.inject at line tri3.rb:3 + #2 Object.triangle(n#Fixnum) at line tri3.rb:3 + #3 at line tri3.rb:7 +(rdb:1) +@end smallexample +Because a new scope was entered, it appears as a stack frame. Probably +``scope'' frame would be a more appropriate name. + +@node More Frequent Evaluations per Line +@subsection More Frequent Evaluations per Line +Consider this simple program to compute the Greatest Common Divisor of +two numbers: +@smallexample + 1 #!/usr/bin/env ruby + 2 # GCD. We assume positive numbers + 3 + 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end + 9 +10 return nil if a <= 0 +11 +12 if a == 1 or b-a == 0 +13 return a +14 end +15 return gcd(b-a, a) +16 end +17 +18 a, b = ARGV[0..1].map @{|arg| arg.to_i@} +19 puts "The GCD of %d and %d is %d" % [a, b, gcd(a, b)] +@end smallexample + +Now let's try tracing a portion of the program to see what we get. +@smallexample +$ @b{rdebug gcd.rb 3 5} +gcd.rb:4 +def gcd(a, b) +(rdb:1) @b{step} +gcd.rb:18 +a, b = ARGV[0..1].map @{|arg| arg.to_i@} +(rdb:1) @b{step} +gcd.rb:18 +a, b = ARGV[0..1].map @{|arg| arg.to_i@} +(rdb:1) @b{step} +gcd.rb:18 +a, b = ARGV[0..1].map @{|arg| arg.to_i@} +(rdb:1) @b{step} +(rdb:1) @b{break Object.gcd} +Breakpoint 1 at Object::gcd +(rdb:1) @b{continue} +Breakpoint 1 at Object:gcd +gcd.rb:4 +def gcd(a, b) +(rdb:1) @b{set linetrace on} +line tracing is on. +(rdb:1) @b{continue} +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Breakpoint 1 at Object:gcd +gcd.rb:4 +def gcd(a, b) +(rdb:1) +@end smallexample + +The thing to note here is that we see lots of lines duplicated. For +example, the first line: +@smallexample +Tracing(1):gcd.rb:18 a, b = ARGV[0..1].map @{|arg| arg.to_i@} +@end smallexample +appears three times. If we were to break this line into the equivalent +multi-line expression: +@smallexample +a, b = ARGV[0..1].map do |arg| + arg.to_i +end +@end smallexample +we would find one stop at the first line before running @code{map} and +two listings of @code{arg.to_i}, once for each value of arg which here +is 0 and then 1. Perhaps this is is not surprising because we have a +loop here which gets run in this situation 3 times. A similar command +@code{next}, can also be used to skip over loops and method +calls. + +But what about all the duplicated @code{if} statements in @code{gcd}? +Each one is listed twice whether or not we put the @code{if} at the +beginning or the end. You will find this to be the case for any +conditional statement such as @code{until} or @code{while}. + +Each statement appears twice because we stop once before the +expression is evaluated and once after the expression is evaluated but +before the if statement takes hold. There is a bug in Ruby up to +version 1.8.6 in that we stop a second time before the evaluation, so +examining values that may have changed during the expression +evaluation doesn't work in these versions. + +If you are issuing a @code{step} command one at a time, the repetitive +nature can be little cumbersome if not annoying. So @value{DBG} offers +a variant called @code{step+} which forces a new line on every +step. Let's try that. +@smallexample +(rdb:1) @b{R} +Re exec'ing: + /usr/bin/rdebug gcd.rb 3 5 +gcd.rb:4 +def gcd(a, b) +(rdb:1) @b{step+} +gcd.rb:18 +a, b = ARGV[0..1].map @{|arg| arg.to_i@} +(rdb:1) @b{step+} +gcd.rb:19 +puts "The GCD of %d and %d is %d" % [a, b, gcd(a, b)] +(rdb:1) @b{break Object.gcd} +Breakpoint 1 at Object:gcd +(rdb:1) @b{c} +Breakpoint 1 at Object:gcd +gcd.rb:4 +def gcd(a, b) +(rdb:1) @b{set linetrace+} +line tracing style is different consecutive lines. +(rdb:1) @b{set linetrace on} +line tracing is on. +(rdb:1) @b{c} +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Breakpoint 1 at Object:gcd +gcd.rb:4 +def gcd(a, b) +@end smallexample + +If you want @code{step+} to be the default behavior when stepping, +issue the command @code{set forcestep on}, (@pxref{Forcestep}). I +generally put this in my start-up file @code{.rdebugrc}. + +Similar to the difference between @code{step+} and @code{step} is +@code{set linetrace+}. This removes duplicate consecutive line tracing. + +One last thing to note above is the use of a method name to set a +breakpoint position, rather than a file and line number. Because +method @code{gcd} is in the outermost scope, we use @code{Object} as the +class name. + +@node Bouncing Around in Blocks (e.g. Iterators) +@subsection Bouncing Around in Blocks (e.g.@: Iterators) + +When debugging languages with coroutines like Python and Ruby, a +method call may not necessarily go to the first statement after the +method header. It's possible the call will continue after a +@code{yield} statement from a prior call. + +@smallexample + 1 #!/usr/bin/env ruby + 2 # Enumerator for primes + 3 class SievePrime + 4 @@@@odd_primes = [] + 5 def self.next_prime(&block) + 6 candidate = 2 + 7 yield candidate + 8 not_prime = false + 9 candidate += 1 +10 while true do +11 @@@@odd_primes.each do |p| +12 not_prime = (0 == (candidate % p)) +13 break if not_prime +14 end +15 unless not_prime +16 @@@@odd_primes << candidate +17 yield candidate +18 end +19 candidate += 2 +20 end +21 end +22 end +23 SievePrime.next_prime do |prime| +24 puts prime +25 break if prime > 10 +26 end +@end smallexample + +@smallexample +$ @b{rdebug primes.rb} +primes.rb:3 +class SievePrime +(rdb:1) @b{set linetrace on} +line tracing is on. +(rdb:1) @b{step 10} +Tracing(1):primes.rb:4 @@odd_primes = [] +Tracing(1):primes.rb:5 def self.next_prime(&block) +Tracing(1):primes.rb:23 SievePrime.next_prime do |prime| +Tracing(1):primes.rb:6 candidate = 2 +Tracing(1):primes.rb:7 yield candidate +Tracing(1):primes.rb:24 puts prime +2 +Tracing(1):primes.rb:25 break if prime > 10 +Tracing(1):primes.rb:25 break if prime > 10 +Tracing(1):primes.rb:8 not_prime = false +Tracing(1):primes.rb:9 candidate += 1 +primes.rb:9 +candidate += 1 +(rdb:1) +@end smallexample + +The loop between lines 23--26 gets interleaved between those of +@code{Sieve::next_prime}, lines 6--19 above. + +A similar kind of thing can occur in debugging programs with many threads. + +@node No Parameter Values in a Call Stack +@subsection No Parameter Values in a Call Stack +In traditional debuggers in a call stack you can generally see the +names of the parameters and the values that were passed in. + +Ruby is a very dynamic language and it tries to be efficient within +the confines of the language definition. Values generally aren't taken +out of a variable or expression and pushed onto a stack. Instead a new +scope created and the parameters are given initial values. Parameter +passing is by @emph{reference}, not by value as it is say Algol, C, or +Perl. During the execution of a method, parameter values can +change---and often do. In fact even the @emph{class} of the object can +change. + +So at present, the name of the parameter shown. The call-style setting +@pxref{Callstyle} can be used to set whether the name is shown or the +name and the @emph{current} class of the object. + +It has been contemplated that a style might be added which saves on +call shorter ``scalar'' types of values and the class name. + +@node Lines You Can Stop At +@subsection Lines You Can Stop At +As with the duplicate stops per control (e.g.@: @code{if} statement), +until tools like debuggers get more traction among core ruby +developers there are going to be weirdness. Here we describe the +stopping locations which effects the breakpoint line numbers you can +stop at. + +Consider the following little Ruby program. + +@smallexample +'Yes it does' =~ / +(Yes) \s+ +it \s+ +does +/ix +puts $1 +@end smallexample + +The stopping points that Ruby records are the last two lines, lines 5 +and 6. If you run @code{ruby -rtracer} on this file you'll see that +this is so: + +@smallexample +$ ruby -rtracer lines.rb +#0:lines.rb:5::-: /ix +#0:lines.rb:6::-: puts $1 +#0:lines.rb:6:Kernel:>: puts $1 +#0:lines.rb:6:IO:>: puts $1 +Yes#0:lines.rb:6:IO:<: puts $1 +#0:lines.rb:6:IO:>: puts $1 + +#0:lines.rb:6:IO:<: puts $1 +#0:lines.rb:6:Kernel:<: puts $1 +@end smallexample + +Inside @code{ruby-debug} you an get a list of stoppable lines for a +file using the @code{info file} command with the attribute +@code{breakpoints}. + +@ifset FINISHED +To be continued... + +@itemize @bullet +@item more complex example with objects, pretty printing and irb. +@item line tracing and non-interactive tracing. +@item mixing in Debugger.debug with rdebug +@item post-mortem debugging and setting up for that +@item threading? +@item references to videos +@end itemize +@end ifset + +@node Invocation +@chapter Getting in and out + +@menu +* Starting the debugger:: How to enter the debugger +* Command Files:: Command files +* Quitting the debugger:: How to leave the debugger (quit, kill) +* Calling from Program:: Calling the debugger from inside your program +@end menu + +It is also possible to enter the debugger when you have an uncaught +exception. See See also @ref{Post-Mortem Debugging}. + +@node Starting the debugger +@section Starting the debugger + +Although one can enter @DBG{} via Emacs (described in a later section) +and possibly others interfaces, probably the most familiar thing to do +is invoke the debugger from a command line. + +A wrapper shell script called @code{rdebug} basically @code{require}'s +the gem package @code{ruby-debug} and then loads @code{rdebug}. + +@smallexample +rdebug [rdebug-options] [--] @var{ruby-script} @var{ruby-script-arguments...} +@end smallexample + +If you don't need to pass dash options to your program which might get +confused with the debugger options, then you don't need to add the +@option{--}. + +To get a brief list of options and descriptions, use the @code{--help} +option. + +@smallexample +$ @b{rdebug --help} +rdebug @value{RDEBUG_VERSION} +Usage: rdebug [options] -- + +Options: + -A, --annotate LEVEL Set annotation level + -c, --client Connect to remote debugger + --cport PORT Port used for control commands + -d, --debug Set $DEBUG=true + --emacs Activates full Emacs support + --emacs-basic Activates basic Emacs mode + -h, --host HOST Host name used for remote debugging + -I, --include PATH Add PATH to $LOAD_PATH + --keep-frame-binding Keep frame bindings + -m, --post-mortem Activate post-mortem mode + --no-control Do not automatically start control thread + --no-quit Do not quit when script finishes + --no-rewrite-program Do not set $0 to the program being debugged + --no-stop Do not stop when script is loaded + -p, --port PORT Port used for remote debugging + -r, --require SCRIPT Require the library, before executing your script + --script FILE Name of the script file to run + -s, --server Listen for remote connections + -w, --wait Wait for a client connection, implies -s option + -x, --trace Turn on line tracing + +Common options: + --verbose Turn on verbose mode + --help Show this message + --version Print the version + -v Print version number, then turn on verbose mode +@end smallexample + +Options for the @code{rdebug} are shown in the following list. + +@menu +* rdebug command-line options:: Options you can pass to rdebug +* rdebug default options:: How to Set Default Command-Line Options +@end menu + +@node rdebug command-line options +@subsection Options you can pass to rdebug + +You can run @DBG{} in various alternative modes---for example, as a +program that interacts directly with the program in the same process +on the same computer or via a socket to another process possibly on a +different computer. + +Many options appear as a long option name, such as @option{--help}, and +a short one letter option name, such as @option{-h}. A double dash +(@option{--} is used to separate options which go to @code{rdebug} from +options that are intended to go to your Ruby script. Options (if any) +to @code{rdebug} should come first. If there is no possibility of the +Ruby script to be debugged getting confused with @code{rdebug}'s +option the double dash can be omitted. + +@table @code +@item --help +@cindex @option{-h} +@cindex @option{--help} +This option causes @ttDBG{} to print some basic help and exit. + +@item -v | --version +@cindex @option{-v} +This option causes @ttDBG{} to print its version number and exit. + +@item -A | --annotate @var{level} +@cindex @option{-A} +@cindex @option{--annotation} @var{level} +Set gdb-style annotation @var{level}, a number. Additional information is output +automatically when program state is changed. This can be used by +front-ends such as GNU Emacs to post this updated information without +having to poll for it. +@item -c | --client +@cindex @option{-c} +@cindex @option{--client} +Connect to remote debugger. The remote debugger should have been set +up previously our you will get a connection error and @code{rdebug} +will terminate. + +@item --cport @var{port} +@cindex @option{--cport} @var{port} +Port used for control commands. + +@item --debug +@cindex @option{--debug} +Set @code{$DEBUG} to @code{true}. This option is compatible with +Ruby's. + +@item --emacs +Activates GNU Emacs mode. +@c @pxref{GNU Emacs}. +Debugger output is tagged in such a way to allow GNU Emacs to track +where you are in the code. + +@item --emacs-basic +Activates full GNU Emacs mode. +@c (@pxref{GNU Emacs}). +This is the equivalent of setting the options @option{--emacs-basic}, +@code{annotate=3}, @option{--no-stop}, @option{-no-control} and +@option{--post-mortem}. + +@item -h | --host @var{host-address} +Connect host address for remote debugging. + +@item -I --include @var{PATH} +@cindex @option{-I} @var{PATH} +@cindex @option{--include} @var{PATH} +Add @var{PATH} to @code{$LOAD_PATH} + +@item --keep-frame-binding +@cindex @option{--keep-frame-binding} +Bindings are used to set the proper environment in evaluating +expression inside the debugger. Under normal circumstances, I don't +believe most people will ever need this option. + +By default, the debugger doesn't create binding object for each frame +when the frame is created, i.e. when a call is performed. Creating a +binding is an expensive operation and has been a major source of +performance problems. + +Instead, the debugger creates a binding when there is a need to +evaluate expressions. The artificial binding that is created might be +different from the real one. In particular, in performing constant +and module name resolution. + +However it's still possible to restore the old, slower behavior by +using this option or by setting @code{Debugger.keep_frame_binding = +true}. There are two possibilities for which you might want to use +this option. + +First, if you think there's a bug in the evaluation of variables, you +might want to set this to see if this corrects things. + +Second, since the internal structures that are used here @code{FRAME} +and @code{SCOPE} are not part of the Ruby specification, it is +possible they can change with newer releases; so here this option this +may offer a remedy. (But you'll probably also have to hack the C code +since it's likely under this scenario that ruby-debug will no longer +compile.) In fact, in Ruby 1.9 these structures have changed and that +is partly why this debugger doesn't work on Ruby 1.9. + +@item -m | --post-mortem +@cindex @option{-m} +@cindex @option{--post-mortem} +If your program raises an exception that isn't caught you can enter +the debugger for inspection of what went wrong. You may also want to +use this option in conjunction with @option{--no-stop}. See also +@ref{Post-Mortem Debugging}. + +@item --no-control +@cindex @option{--no-control} +Do not automatically start control thread. + +@item --no-quit +@cindex @option{--no-quit} +Restart the debugger when your program terminates normally. + +@item --no-rewrite-program +@cindex @option{--no-rewrite-program} +Normally @code{rdebug} will reset the program name @code{$0} from its +name to the debugged program, and set the its name in variable +@code{$RDEBUG_0}. In the unlikely even you don't want this use this option. + +@item --no-stop +@cindex @option{--no-stop} +Normally the @code{rdebug} stops before executing the first +statement. If instead you want it to start running initially and will +perhaps break it later in the running, use this options. + +@item -p | --port @var{port} +@cindex @option{-p} @var{port} +@cindex @option{--port} @var{port} +Port used for remote debugging. + +@item -r | --require @var{library} +@cindex @option{-r} +@cindex @option{--require} +Require the library, before executing your script. However if the +library happened to be @code{debug}, we'll just ignore the require +(since we're already a debugger). This option is compatible with Ruby's. + +@item --script @var{file} +@cindex @option{--script} +Require the library, before executing your script. However if the +library hap-pend to be @code{debug}, we'll just ignore the require +(since we're already a debugger). This option is compatible with Ruby's. + +@item -s | --server +@cindex @option{-s} +@cindex @option{--server} +Debug the program but listen for remote connections on the default +port or port set up via the @option{--port} option. See also @option{--wait}. + +@item -w | --wait +@cindex @option{-w} +@cindex @option{--wait} +Debug the program but stop waiting for a client connection first. This +option automatically sets @option{--server} option. + +@item -x | --trace +@cindex @option{-x} +@cindex @option{--trace} +Turn on line tracing. Running @command{rdebug --trace @emph{rubyscript.rb}} +is much like running: @command{ruby -rtracer @emph{rubyscript.rb}} + +If all you want to do however is get a linetrace, @code{tracer}, not +@code{rdebug}, may be faster: +@smallexample +$ @b{time ruby -rtracer gcd.rb 34 21 > /dev/null} + +real 0m0.266s +user 0m0.008s +sys 0m0.000s +$ @b{time rdebug --trace gcd.rb 34 21 > /dev/null} + +real 0m0.875s +user 0m0.448s +sys 0m0.056s +$ +@end smallexample + +@end table + +@node rdebug default options +@subsection How to Set Default Command-Line Options + +@DBG{} has many command-line options; it seems that some people want +to set them differently from the our defaults. For example, some +people may want @option{--no-quit --no-control} to be the default +behavior. One could write a wrapper script or set a shell alias to +handle this. @DBG{} has another way to do this as well. Before +processing command options if the file @code{$HOME/.rdboptrc} is found +it is loaded. If you want to set the defaults in some other way, you +can put Ruby code here and set variable @code{options} which is an +OpenStruct. For example here's how you'd set @option{-no-quit} and +change the default control port to 5000. + +@smallexample +# This file contains how you want the default options to ruby-debug +# to be set. Any Ruby code can be put here. +# +# debugger # Uncomment if you want to debug rdebug! +options.control = false +options.port = 5000 +puts "rocky's rdboptrc run" +@end smallexample + +Here are the default values in @code{options} +@smallexample +# +@end smallexample + + +@node Command Files +@section Command files + +@cindex command files +A command file for @DBG{} is a file of lines that are @DBG{} +commands. Comments (lines starting with @kbd{#}) may also be included. +An empty line in a command file does nothing; it does not mean to repeat +the last command, as it would from the terminal. + +@cindex init file +@cindex @file{.rdebugrc} +When you start @value{DBG}, it automatically executes commands from its +@dfn{init files}, normally called @file{.rdebugrc}. + +On some configurations of @value{DBG}, the init file may be known by a +different name. In particular on MS-Windows (but not cygwin) +@file{rdebug.ini} is used. + +During startup, @DBG{} does the following: + +@enumerate +@item +Processes command line options and operands. + +@item +Reads the init file in your current directory, if any, and failing +that the home directory. The home directory is the directory named in +the @code{HOME} or @code{HOMEPATH} environment variable. + +Thus, you can have more than one init file, one generic in your home +directory, and another, specific to the program you are debugging, in +the directory where you invoke @DBG{}. + +@item +Reads command files specified by the @samp{--script} option. +@end enumerate + +You can also request the execution of a command file with the +@code{source} command, @pxref{Source}. + +@node Quitting the debugger +@section Quitting the debugger + +@cindex interrupt +An interrupt (often @kbd{C-c}) does not exit from @value{DBG}, but +rather terminates the action of any @DBG command that is in +progress and returns to @value{DBG} command level. Inside a debugger +command interpreter, use @code{quit} command (@pxref{Control, ,Quitting +the debugger}). + +There way to terminate the debugger is to use the @code{kill} +command. This does more forceful @code{kill -9}. It can be used in +cases where @code{quit} doesn't work. + +@node Calling from Program +@section Calling the debugger from inside your Ruby program + +Running a program from the debugger adds a bit of overhead and slows +down your program a little. + +Furthermore, by necessity, debuggers change the operation of the +program they are debugging. And this can lead to unexpected and +unwanted differences. It has happened so often that the term +``Heisenbugs'' (see @url{http://en.wikipedia.org/wiki/Heisenbug}) was +coined to describe the situation where the addition of the use of a +debugger (among other possibilities) changes behavior of the program +so that the bug doesn't manifest itself anymore. + +There is another way to get into the debugger which adds no overhead +or slowdown until you reach the point at which you want to start +debugging. However here you must change the script and make an +explicit call to the debugger. Because the debugger isn't involved +before the first call, there is no overhead and the script will run +at the same speed as if there were no debugger. + +There are three parts to calling the debugger from inside the script, +``requiring'' the debugger code, telling the debugger to start +tracking things and then making the call calling the debugger to +stop. + +To get the debugger class accessible from your Ruby program: + +@smallexample +require 'rubygems' +require 'ruby-debug' +@end smallexample +(It is very likely that you've already require'd rubygems. If so, you +don't have to do that again.) These commands need to be done only +once. + +After @code{require 'ruby-debug'}, it's possible to set some of the +debugger variables influence preferences. For example if you want to +have @ttDBG run a @code{list} command every time it stops you set the +variable @code{Debugger.settings[:autolist]}. @pxref{Debugger.settings} has a +list of variable settings and the default values. Debugger settings +can also be set in @code{.rdebugrc} as debugger +commands. @pxref{Command Files} + +To tell the debugger to start tracking things: + +@smallexample +Debugger.start +@end smallexample + +There is also a @code{Debugger.stop} to turn off debugger tracking. If +speed is crucial, you may want to start and stop this around certain +sections of code. Alternatively, instead of issuing an explicit +@code{Debugger.stop} you can add a block to the @code{Debugger.start} +and debugging is turned on for that block. If the block of code raises +an uncaught exception that would cause the block to terminate, the +@code{stop} will occur. See @ref{Debugger.start with a block}. + +And finally to enter the debugger: + +@smallexample +debugger +@end smallexample + +As indicated above, when @code{debugger} is run a @code{.rdebugrc} +profile is read if that file exists. + +You may want to do enter the debugger at several points in the program +where there is a problem you want to investigate. And since +@code{debugger} is just a method call it's possible enclose it in a +conditional expression, for example: +@smallexample +debugger if 'bar' == foo and 20 == iter_count +@end smallexample + +Although each step does a very specific thing which offers great +flexibility, in order to make getting into the debugger easier the +three steps have been rolled into one command: +@smallexample +require "ruby-debug/debugger" +@end smallexample + +@node Debugger Command Reference +@chapter @code{ruby-debug} Command Reference + +@menu +* Command Interfaces:: The kinds of interface used to interact with ruby-debug +* Command Syntax:: How to give commands to the ruby-debug +* Command Output:: How rdebug presents its output +* Help:: How to ask for help (help) +* Control:: Controlling the debugger (quit, restart, interrupt) +* DisplayCommands:: Executing expressions on stop (display, undisplay) +* PrintCommands:: Evaluating and Printing Expressions (p, pp, ps, pp, irb) +* PrintVars:: Printing Variables (var) +* List:: Examining Program Source Files (list) +* Edit:: Editing source files (edit) +* FrameCommands:: Examining the stack frame (where, up, down, frame) +* Stopping:: Stopping and continuing (break, watch, step, cont...) +* ruby-debug settings:: rdebug-settings (set args, set autoeval, ...) +* Program Information:: Program Status (info) +@end menu + +@node Command Interfaces +@section Command Interfaces +There are several ways one can talk to @code{ruby-debug} and get +results. The simplest way is via a command-line interface directly +talking to the debugger. This is referred to below as a ``Local +Interface''. It's also possible to run the debugger and set up a port +by which some other process can connect and control the debug +session. This is called a ``Remote Interface''. When you want to gain +access to a remote interface you need to run @code{ruby-debug} using a +``Control Interface''. This interface might not be the same process as +the process running the debugged program and might not even be +running on the same computer. + +Other front-ends may use one of these and build on top and provide +other (richer) interfaces. Although many of the commands are available +on all interfaces some are not. Most of the time in this manual when +we talk about issuing commands describing the responses elicited, +we'll assume we are working with the local interface. + +@node Command Syntax +@section Command Syntax +Usually a command is put on a single line. There is no limit on how long +it can be. It starts with a command name, which is followed by +arguments whose meaning depends on the command name. For example, the +command @code{step} accepts an argument which is the number of times to +step, as in @code{step 5}. You can also use the @code{step} command with no +arguments. Some commands do not allow any arguments. + +Multiple commands can be put on a line by separating each with a +semicolon (@code{;}). You can disable the meaning of a semicolon to +separate commands by escaping it with a backslash. + +For example, if you have @code{autoeval} (@ref{Autoeval}) set, you +might want to enter the following code to compute the 5th Fibonacci +number: +@smallexample +# Compute the 5 Fibonaci number +(rdb:1) set autoeval on +(rdb:1) fib1=0; fib2=1; 5.times @{|temp| temp=fib1; fib1=fib2; fib2 += temp @} +SyntaxError Exception: compile error +/usr/bin/irb:10: syntax error, unexpected $end, expecting '@}' + 5.times @{|temp| temp=fib1 + ^ +(rdb:1) fib1=0\; fib2=1\; 5.times @{|temp| temp=fib1\; fib1=fib2\; fib2 += temp @} +5 +(rdb:1) fib2 +fib2 +8 +@end smallexample +You might also consider using the @code{irb} command, @ref{irb}, and +then you won't have to escape semicolons. + +A blank line as input (typing just @key{}) means to repeat the +previous command. + +In the ``local'' interface, the Ruby Readline module is used. It +handles line editing and retrieval of previous commands. Up arrow, for +example moves to the previous debugger command; down arrow moves to +the next more recent command (provided you are not already at the last +command). Command history is saved in file @code{.rdebug_hist}. A +limit is put on the history size. You can see this with the @code{show +history size} command. See @ref{History} for history parameters. + +@node Command Output +@section Command Output + +In the command-line interface, when @code{ruby-debug} is waiting for +input it presents a prompt of the form +@code{(rdb:}@emph{x}@code{)}. If debugging locally, @emph{x} will be +the thread number. Usual the main thread is 1, so often you'll see +@code{(rdb:1)}. In the control interface though @emph{x} will be +@code{ctrl} and in post-mortem debugging @code{post-mortem}. + +In the local interface, whenever @code{ruby-debug} gives an error +message such as for an invalid command, or an invalid location +position, it will generally preface the message with +@code{***}. However if annotation mode is on that the message is put +in a @code{begin-error} annotation and no @code{***} appears. + +@node Help +@section Getting help (@samp{help}) +@cindex on-line documentation +@menu +* Help for Subcommands:: +@end menu + +Once inside @code{ruby-debug} you can always ask it for information on +its commands, using the command @code{help}. + +@table @code +@kindex h @r{(@code{help})} +@kindex help @ovar{command-name} +@item help +@itemx h +You can use @code{help} (abbreviated @code{h}) with no arguments to +display a short list of named classes of commands: + +@flushleft +@smallexample +(rdb:1) @b{help} +ruby-debug help v@value{RDEBUG_VERSION} +Type 'help ' for help on a specific command + +Available commands: +backtrace delete enable help next quit show undisplay +break disable eval info p reload source up +catch display exit irb pp restart step var +condition down finish list ps save thread where +continue edit frame method putl set trace +@end smallexample +@end flushleft +@c the above line break eliminates huge line overfull... + +@end table + +@table @code +@item help @var{command} +With a command name as @code{help} argument, @DBG displays short +information on how to use that command. + +@smallexample +(rdb:1) @b{help list} +ruby-debug help v@value{RDEBUG_VERSION} +l[ist] list forward +l[ist] - list backward +l[ist] = list current line +l[ist] nn-mm list given lines +* NOTE - to turn on autolist, use 'set autolist' +(rdb:1) +@end smallexample +@end table + +@node Help for Subcommands +@subsection Help on Subcommands +A number of commands have many sub-parameters or +@emph{subcommands}. These include @code{info}, @code{set}, +@code{show}, @code{enable} and @code{disable}. + +When you ask for help for one of these commands, you will get help for +all of the subcommands that that command offers. Sometimes you may +want help that subcommand and to do this just follow the command with +its subcommand name. For example @code{help set annotate} will just +give help about the annotate command. Furthermore it will give longer +help than the summary information that appears when you ask for +help. You don't need to list the full subcommand name, but just enough +of the letters to make that subcommand distinct from others will +do. For example, @code{help set an} is the same as @code{help set annotate}. + +Some examples follow. +@example +(rdb:1) @b{help info} +Generic command for showing things about the program being debugged. +-- +List of info subcommands: +-- +info args -- Argument variables of current stack frame +info breakpoints -- Status of user-settable breakpoints +info catch -- Exceptions that can be caught in the current stack frame +info display -- Expressions to display when program stops +info file -- Info about a particular file read in +info files -- File names and timestamps of files read in +info global_variables -- Global variables +info instance_variables -- Instance variables of the current stack frame +info line -- Line number and file name of current position in source file +info locals -- Local variables of the current stack frame +info program -- Execution status of the program +info stack -- Backtrace of the stack +info thread -- List info about thread NUM +info threads -- information of currently-known threads +info variables -- Local and instance variables of the current stack frame +@end example + +@example +(rdb:1) @b{help info breakpoints} +Status of user-settable breakpoints. +Without argument, list info about all breakpoints. With an +integer argument, list info on that breakpoint. +@end example + +@example +(rdb:1) @b{help info br} +Status of user-settable breakpoints. +Without argument, list info about all breakpoints. With an +integer argument, list info on that breakpoint. +@end example + +@node Control +@section Controlling the debugger (@samp{quit}, @samp{restart}, @samp{interrupt}, @samp{source}) + +@menu +* Quit:: Quitting the debugger (quit) +* Restart:: Restarting Script execution (restart) +* Interrupt:: Interrupting the debugger (interrupt) +* Source:: Running Debugger commands (source) +@end menu + +@node Quit +@subsection Quit (@samp{quit}) +@table @code +@kindex quit @r{[}unconditionally@r{]} +@kindex q @r{(@code{quit})} +@item quit @r{[}unconditionally@r{]} +@item exit +@itemx q + +To exit @value{DBG}, use the @code{quit} command (abbreviated +@code{q}), or alias @code{exit}. + +A simple @code{quit} tries to terminate all threads in effect. + +Normally if you are in an interactive session, this command will +prompt to ask if you really want to quit. If you don't want any +questions asked, enter the ``unconditionally''. + +@end table + +@node Restart +@subsection Restart (@samp{restart}) +@table @code +@kindex restart @r{[}@var{program args}@r{]} +@kindex R @r{(@code{restart})} +@item restart +@itemx R + +Restart the program. This is is a re-exec - all debugger state is +lost. If command arguments are passed those are used. Otherwise the +last program arguments used in the last invocation are used. + +In not all cases will you be able to restart the program. First, the +program should have been invoked at the outset rather than having been +called from inside your program or invoked as a result of post-mortem +handling. + +Also, since this relies on the the OS @code{exec} call, this command +is available only if your OS supports that @code{exec}; OSX for +example does not (yet). +@end table + +@node Interrupt +@subsection Interrupt (@samp{interrupt}) +@table @code +@kindex interrupt +@kindex i +@item interrupt +@itemx i +Interrupt the program. Useful if there are multiple threads running. +@end table + +@node Source +@subsection Running Debugger Commands (@samp{source}) +@table @code +@kindex source @var{filename} +@item source @var{filename} +Execute the command file @var{filename}. + +The lines in a command file are executed sequentially. They are not +printed as they are executed. If there is an error, execution +proceeds to the next command in the file. For information about +command files that get run automatically on startup, @pxref{Command Files}. +@end table + +@node DisplayCommands +@section Executing expressions on stop (@samp{display}, @samp{undisplay}) +@cindex automatic display +@cindex display of expressions + +If you find that you want to print the value of an expression +frequently (to see how it changes), you might want to add it to the +@dfn{automatic display list} so that @value{DBG} evaluates a statement +each time your program stops or the statement is shown in line tracing. +Each expression added to the list is given a number to identify it; to +remove an expression from the list, you specify that number. The +automatic display looks like this: + +@smallexample +(rdb:1) display n +1: n = 3 +@end smallexample + +@noindent +This display shows item numbers, expressions and their current values. +If the expression is undefined or illegal the expression will be +printed but no value will appear. + +@smallexample +(rdb:1) display undefined_variable +2: undefined_variable = +(rdb:1) display 1/0 +3: 1/0 = +@end smallexample + +Note: this command uses @code{to_s} to in expressions; for example an +array @code{[1, 2]} will appear as @code{12}. For some datatypes like +an Array, you may want to call the @code{inspect} method, for example +@code{display ARGV.inspect} rather than @code{display ARGV}. + +@table @code +@kindex display @ovar{expr} +@item display @var{expr} +Add the expression @var{expr} to the list of expressions to display +each time your program stops or a line is printed when linetracing is +on (@pxref{DisplayCommands}). + +@item display +Display the current values of the expressions on the list, just as is +done when your program stops. + +@kindex undisplay @ovar{num} +@item undisplay @ovar{num} +@itemx delete display @var{num} +Remove item number @var{num} from the list of expressions to display. + +@kindex info display +@item info display +Show all display expressions + +@ifset GDB_COMPLETED +@code{undisplay} does not repeat if you press @key{RET} after using it. +(Otherwise you would just get the error @samp{No display number @dots{}}.) +@end ifset + +@kindex disable display +@item disable display @var{dnums}@dots{} +Disable the display of item numbers @var{dnums}. A disabled display +item is not printed automatically, but is not forgotten. It may be +enabled again later. + +@kindex enable display +@item enable display @var{dnums}@dots{} +Enable display of item numbers @var{dnums}. It becomes effective once +again in auto display of its expression, until you specify otherwise. + +@end table + +@node PrintCommands +@section Evaluating and Printing Expressions (@samp{p}, @samp{pp}, @samp{putl}, @samp{ps}, @samp{irb}) + +One way to examine and change data in your script is with the +@code{eval} command (abbreviated @code{p}). A similar command is +@code{pp} which tries to pretty print the result. Finally @code{irb} is +useful when you anticipate examining or changing a number of things, +and prefer not to have to preface each command, but rather work as one +does in @code{irb}. + +@menu +* eval:: eval or print an expression (eval, p) +* pp:: pretty print an expression (pp, ps, putl) +* irb:: running irb using the current context +@end menu + +@node eval +@subsection Printing an expression (@samp{eval}, @samp{p}) +@table @code +@kindex eval @var{expr} +@kindex p @r{(@code{eval})} +@item eval @var{expr} +@itemx p @var{expr} + +Use @code{eval} or @code{p} to evaluate a Ruby expression, @var{expr}, +same as you would if you were in @code{irb}. If there are many expressions +you want to look at, you may want to go into irb from the debugger. +@smallexample +@group +(rdb:p) p n +3 +(rdb:1) p "the value of n is #@{n@}" +"the value of n is 3" +(rdb:1) +@end group +@end smallexample +@end table + +@node pp +@subsection Pretty-Printing an expression (@samp{pp}, @samp{putl}, @samp{ps})) +@table @code +@item pp +@kindex pp @var{expr} +Evaluates and pretty-prints @var{expr} +@smallexample +@group +(rdb:1) @b{p $LOAD_PATH} +["/home/rocky/lib/ruby", "/usr/lib/ruby/site_ruby/1.8", "/usr/lib/ruby/site_ruby/1.8/i586-linux", "/usr/lib/ruby/1.8"] +(rdb:1) @b{pp $LOAD_PATH} +["/home/rocky/lib/ruby", + "/usr/lib/ruby/site_ruby/1.8", + "/usr/lib/ruby/site_ruby/1.8/i586-linux", + "/usr/lib/ruby/1.8"] +@end group +@end smallexample +@kindex putl +@item putl +If the value you want to print is an array, sometimes a columnized +list looks nicer: +@smallexample +@group +(rdb:1) @b{putl $LOAD_PATH} +/home/rocky/lib/ruby /usr/lib/ruby/site_ruby/1.8 +/usr/lib/ruby/site_ruby/1.8/i586-linux /usr/lib/ruby/1.8 +@end group +@end smallexample + +Note however that entries are sorted to run down first rather than +across. So in the example above the second entry in the list is +@code{/usr/lib/ruby/site_ruby/1.8/i586-linux} and the @emph{third} entry is +@code{/usr/lib/ruby/site_ruby/1.8}. + +If the value is not an array @code{putl} will just call pretty-print. +@kindex ps +@item ps +Sometimes you may want to print the array not only columnized, but +sorted as well. The list of debugger help commands appears this way, +and so does the output of the @code{method} commands. + +@smallexample +@group +(rdb:1) ps Kernel.private_methods +Digest initialize y +Pathname initialize_copy +Rational location_of_caller +active_gem_with_options method_added +alias_method method_removed +append_features method_undefined +attr module_function +attr_accessor private +attr_reader protected +attr_writer public +class_variable_get remove_class_variable +class_variable_set remove_const +define_method remove_instance_variable +extend_object remove_method +extended singleton_method_added +gcd singleton_method_removed +gem_original_require singleton_method_undefined +include timeout +included undef_method +@end group +@end smallexample + +If the value is not an array, @code{ps} will just call pretty-print. +See also the @code{methods}. +@end table + +@node irb +@subsection Run irb (@samp{irb}) +@table @code +@kindex irb +@item irb +Run an interactive ruby session (@code{irb}) with the bindings +environment set to the state you are in the program. + +When you leave irb and go back to the debugger command prompt we show +again the file, line and text position of the program in the same way +as when entered the debugger. If you issue a @command{list} without +location information, the default location used is the current line +rather than the position may have gotten updated via a prior +@command{list} command. +@smallexample +triangle.rb:4 +def triangle(n) +(rdb:1) @b{list} +[-1, 8] in /home/rocky/ruby/triangle.rb + 1 #!/usr/bin/env ruby + 2 # Compute the n'th triangle number - the hard way + 3 # triangle(n) == (n * (n+1)) / 2 +=> 4 def triangle(n) + 5 tri = 0 + 6 0.upto(n) do |i| + 7 tri += i + 8 end +@b{irb} +>> @b{(0..6).inject@{|sum, i| sum +=i@}} +=> 21 +>> @b{exit} +triangle.rb:4 +def triangle(n) +(rdb:1) @b{list # Note we get the same line range as before going into irb} +[-1, 8] in /home/rocky/ruby/triangle.rb + 1 #!/usr/bin/env ruby + 2 # Compute the n'th triangle number - the hard way + 3 # triangle(n) == (n * (n+1)) / 2 +=> 4 def triangle(n) + 5 tri = 0 + 6 0.upto(n) do |i| + 7 tri += i + 8 end +@end smallexample + +@end table + +@node PrintVars +@section Printing Variables (@samp{var}, @samp{method}) + +@table @code +@item var const @var{object} +@kindex var const @var{expr} +Show the constants of @var{object}. This is basically listing +variables and their values in @var{object}@code{.constant}. +@item var instance @var{object} +@kindex var instance @var{expr} +Show the instance variables of @var{object}. This is basically listing +@var{object}@code{.instance_variables}. +@item info instance_variables +@kindex info instance_variables +Show instance_variables of @code{@@self} +@item info locals +@kindex info locals +Show local variables +@item info globals +@kindex info globals +Show global variables +@item info variables +@kindex info variables +Show local and instance variables of @code{@@self} +@item method instance @var{object} +@kindex method instance @var{object} +Show methods of @var{object}. Basically this is the same as running +@code{ps object.instance_methods(false)} on @var{object}. +@item method iv @var{object} +@kindex method iv @var{object} +Show method instance variables of @var{object}. Basically this is the same as running +@smallexample + obj.instance_variables.each do |v| + puts "%s = %s\n" % [v, obj.instance_variable_get(v)] + end +@end smallexample +on @var{object}. +@item signature @var{object} +@kindex method signature @var{object} +Show procedure signature of method @var{object}. +@emph{This command is available only if the nodewrap is installed.} +@smallexample + def mymethod(a, b=5, &bock) + end + (rdb:1) @b{method sig mymethod} + Mine#mymethod(a, b=5, &bock) +@end smallexample +on @var{object}. +@item method @var{class-or-module} +@kindex method @var{class-or-module} +Show methods of the class or module, @var{class-or-module}. Basically +this is the same as running @code{ps object.methods} on @var{class-or-module}. +on @var{class-or-module}. +@end table + +@node List +@section Examining Program Source Files (@samp{list}) + +@cindex current line +@value{DBG} can print parts of your script's source. When your script +stops, @value{DBG} spontaneously prints the line where it stopped and +the text of that line. Likewise, when you select a stack frame +(@pxref{Selection}) @value{DBG} prints the line where execution in +that frame has stopped. Implicitly there is a default line +location. Each time a list command is run that implicit location is +updated, so that running several list commands in succession shows a +contiguous block of program text. + +You can print other portions of source files by giving an explicit +position as a parameter to the list command. + +If you use @value{DBG} through its Emacs interface, you may prefer to +use Emacs facilities to view source. +@c @pxref{GNU Emacs}. + +@kindex list @ovar{line-number} +@kindex l @r{(@code{list})} +To print lines from a source file, use the @code{list} command +(abbreviated @code{l}). By default, ten lines are printed. Fewer may +appear if there fewer lines before or after the current line to center +the listing around. + +There are several ways to specify what part of the file you want to print. +Here are the forms of the @code{list} command. + +@table @code +@item list @var{line-number} +@itemx l @var{line-number} +Print lines centered around line number @var{line-number} in the +current source file. + +@item list +@itemx l +Print more lines. If the last lines printed were printed with a +@code{list} command, this prints lines following the last lines +printed; however, if the last line printed was a solitary line printed +as part of displaying a stack frame (@pxref{Frames}), this prints lines +centered around that line. + +@item list - +@itemx l - +Print lines just before the lines last printed. +@item list @var{first}-@var{last} +Print lines between @var{first} and @var{last} inclusive. + +@item list = +Print lines centered around where the script is stopped. +@end table + +Repeating a @code{list} command with @key{RET} discards the argument, +so it is equivalent to typing just @code{list}. This is more useful +than listing the same lines again. An exception is made for an +argument of @samp{-}; that argument is preserved in repetition so that +each repetition moves up in the source file. + +@node Edit +@section Editing Source files (@samp{edit}) + +To edit the lines in a source file, use the @code{edit} command. The +editing program of your choice is invoked with the current line set to +the active line in the program. Alternatively, you can give a line +specification to specify what part of the file you want to print if +you want to see other parts of the program. + +You can customize to use any editor you want by using the +@code{EDITOR} environment variable. The only restriction is that your +editor (say @code{ex}), recognizes the following command-line syntax: +@smallexample +ex +@var{number} file +@end smallexample +The optional numeric value +@var{number} specifies the number of the +line in the file where to start editing. For example, to configure +@value{DBG} to use the @code{vi} editor, you could use these commands +with the @code{sh} shell: +@smallexample +EDITOR=/usr/bin/vi +export EDITOR +gdb @dots{} +@end smallexample +or in the @code{csh} shell, +@smallexample +setenv EDITOR /usr/bin/vi +gdb @dots{} +@end smallexample + +@table @code +@kindex edit @ovar{line-specification} +@item edit @ovar{line specification} +Edit line specification using the editor specified by the +@code{EDITOR} environment variable. +@end table + +@node FrameCommands +@section Examining the Stack Frame (@samp{where}, @samp{up}, @samp{down}, @samp{frame}) + +When your script has stopped, one thing you'll probably want to know +is where it stopped and some idea of how it got there. + +@cindex call stack +Each time your script performs a function or sends a message to a +method, or enters a block, information about this action is saved. +The frame stack then is this a history of the blocks that got you to +the point that you are currently stopped at.@footnote{More accurately +we should call this a ``block stack''; but we'll use the name that is +more commonly used. And internally in Ruby, there is ``FRAME'' +structure which is yet slightly different.} + +@cindex selected block +One entry in call stack is @dfn{selected} by @DBG{} and many +@DBG commands refer implicitly to the selected block. In +particular, whenever you ask @DBG to list lines without giving +a line number or location the value is found in the selected frame. +There are special @DBG commands to select whichever frame you +are interested in. @xref{Selection, ,Selecting a frame}. + +When your program stops, @DBG{} automatically selects the +currently executing frame and describes it briefly, similar to the +@code{frame} command. + +After switching frames, when you issue a @code{list} command without +any position information, the position used is location in the frame +that you just switched between, rather than a location that got +updated via a prior @code{list} command. + +@menu +* Frames:: Stack frames +* Backtrace:: Backtraces (where) +* Selection:: Selecting a frame (up, down, frame) + +@end menu + +@node Frames +@subsection Stack frames + +@cindex frame, definition +@cindex stack frame +The block stack is divided up into contiguous pieces called @dfn{stack +frames}, @dfn{frames}, or @dfn{blocks} for short; each frame/block has +a scope associated with it; It contains a line number and the +source-file name that the line refers. If the frame/block is the beginning +of a method or function it also contains the function name. + +@cindex initial frame +@cindex outermost frame +@cindex innermost frame +When your script is started, the stack has only one frame, that of the +function @code{main}. This is called the @dfn{initial} frame or the +@dfn{outermost} frame. Each time a function is called, a new frame is +made. Each time a function returns, the frame for that function invocation +is eliminated. If a function is recursive, there can be many frames for +the same function. The frame for the function in which execution is +actually occurring is called the @dfn{innermost} frame. This is the most +recently created of all the stack frames that still exist. + +@cindex frame number +@value{DBG} assigns numbers to all existing stack frames, starting with +zero for the innermost frame, one for the frame that called it, +and so on upward. These numbers do not really exist in your script; +they are assigned by @value{DBG} to give you a way of designating stack +frames in @value{DBG} commands. + +@node Backtrace +@subsection Backtraces (@samp{where}) + +@cindex backtraces +@cindex tracebacks +@cindex stack traces +A backtrace is essentially the same as the call stack: a summary of +how your script got where it is. It shows one line per frame, for +many frames, starting with the place that you are stopped at (frame +zero), followed by its caller (frame one), and on up the stack. + +@table @code +@kindex where +@kindex w @r{(@code{where})} +@itemx where +Print the entire stack frame; @code{info stack} is an alias for this command. +Each frame is numbered and can be referred to in the @code{frame} +command; @code{up} and @code{down} add or subtract respectively to +frame numbers shown. The position of the current frame is marked with +@code{-->}. + +@smallexample +(rdb:1) where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line /tmp/gcd.rb:6 + #1 at line /tmp/gcd.rb:19 +@end smallexample + +@ifset FINISHED +@item backtrace @var{n} +@itemx bt @var{n} +@itemx where @var{n} +@itemx T @var{n} +Similar, but print only the innermost @var{n} frames. + +@item backtrace -@var{n} +@itemx bt -@var{n} +@itemx where -@var{n} +@itemx T -@var{n} +Similar, but print only the outermost @var{n} frames. +@end ifset +@end table + +@node Selection +@subsection Selecting a frame (@samp{up}, @samp{down}, @samp{frame}) + +Commands for listing source code in your script work on whichever +stack frame is selected at the moment. Here are the commands for +selecting a stack frame; all of them finish by printing a brief +description of the stack frame just selected. + +@table @code +@kindex up @ovar{n} +@item up @ovar{n} +Move @var{n} frames up the stack. For positive numbers @var{n}, this +advances toward the outermost frame, to higher frame numbers, to +frames that have existed longer. Using a negative @var{n} is the same thing +as issuing a @code{down} command of the absolute value of the @var{n}. +Using zero for @var{n} does no frame adjustment, but since the current +position is redisplayed, it may trigger a resynchronization if there is +a front end also watching over things. + +@var{n} defaults to one. You may abbreviate @code{up} as @code{u}. + +@kindex down @ovar{n} +@item down @ovar{n} +Move @var{n} frames down the stack. For positive numbers @var{n}, this +advances toward the innermost frame, to lower frame numbers, to frames +that were created more recently. Using a negative @var{n} is the same +as issuing a @code{up} command of the absolute value of the @var{n}. +Using zero for @var{n} does no frame adjustment, but since the current +position is redisplayed, it may trigger a resynchronization if there is +a front end also watching over things. + +@var{n} defaults to one. +@end table + +@table @code +@kindex frame @r{[}@ovar{n} @r{[}thread @var{thread-num}@r{]}@r{]} +@cindex current stack frame +@item frame @ovar{n} @r{[}thread @var{thread-num}@r{]} +The @code{frame} command allows you to move from one stack frame to +another, and to print the stack frame you select. @var{n} is the the +stack frame number or 0 if no frame number is given; @code{frame 0} +then will always show the current and most recent stack frame. + +If a negative number is given, counting is from the other end of the +stack frame, so @code{frame -1} shows the least-recent, outermost or +most ``main'' stack frame. + +Without an argument, @code{frame} prints the current stack +frame. Since the current position is redisplayed, it may trigger a +resynchronization if there is a front end also watching over +things. + +If a thread number is given then we set the context for evaluating +expressions to that frame of that thread. +@end table + +@node Stopping +@section Stopping and Resuming Execution + +One important use of a debugger is to stop your program @emph{before} +it terminates, so that if your script runs into trouble you can +investigate and find out why. However should your script accidentally +continue to termination, it can be arranged for @DBG to not to leave +the debugger without your explicit instruction. That way, you can +restart the program using the same command arguments. + +Inside @value{DBG}, your script may stop for any of several reasons, +such as a signal, a breakpoint, or reaching a new line after a +debugger command such as @code{step}. You may then examine and +change variables, set new breakpoints or remove old ones, and then +continue execution. + +@menu +* Breakpoints:: Breakpoints (break, catch, delete) +* Disabling:: Disabling breakpoints (disable, enable) +* Conditions:: Break conditions (condition) +* Resuming Execution:: Resuming execution (continue, step, next, finish) +@end menu + +@node Breakpoints +@subsection Breakpoints (@samp{break}, @samp{catch}, @samp{delete}) + +@cindex breakpoints +A @dfn{breakpoint} makes your script stop whenever a certain point in +the program is reached. For each breakpoint, you can add conditions to +control in finer detail whether your script stops. + +You specify the place where your script should stop with the +@code{break} command and its variants. + +@cindex breakpoint numbers +@cindex numbers for breakpoints +@value{ttDBG} assigns a number to each breakpoint when +you create it; these numbers are successive integers starting with +one. In many of the commands for controlling various features of +breakpoints you use the breakpoint number to say which breakpoint you +want to change. Each breakpoint may be @dfn{enabled} or +@dfn{disabled}; if disabled, it has no effect on your script until you +enable it again. + + +@table @code +@kindex break @ovar{location} +@kindex b @r{(@code{break})} +@item break +Set a breakpoint at the current line. + +@item break @var{linenum} +Set a breakpoint at line @var{linenum} in the current source file. +The current source file is the last file whose source text was printed. +The breakpoint will stop your script just before it executes any of the +code on that line. + +@item break @var{filename}:@var{linenum} +Set a breakpoint at line @var{linenum} in source file @var{filename}. + +What may be a little tricky when specifying the filename is getting +the name recognized by the debugger. If you get a message the message +``@code{No source file named ...}'', then you may need to qualify the +name more fully. To see what files are loaded you can use the @code{info +files} or @code{info file} commands. If you want the name @code{rdebug} thinks +of as the current file, use @code{info line}. + +Here's an example: +@example +$ @b{rdebug ~/ruby/gcd.rb 3 5} +/home/rocky/ruby/gcd.rb:4 # Note this is the file name +def gcd(a, b) +(rdb:1) @b{break gcd.rb:6} +*** No source file named gcd.rb +(rdb:1) @b{info line} +Line 4 of "/home/rocky/ruby/gcd.rb" +(rdb:1) @b{break /home/rocky/ruby/gcd.rb:6} +Breakpoint 1 file /home/rocky/ruby/gcd.rb, line 6 +(rdb:1) @b{break ~/ruby/gcd.rb:10} # tilde expansion also works +Breakpoint 2 file /home/rocky/ruby/gcd.rb, line 10 +(rdb:1) @b{info file gcd.rb} +File gcd.rb is not cached +(rdb:1) @b{info file /home/rocky/ruby/gcd.rb} +File /home/rocky/ruby/gcd.rb + 19 lines +@end example + +@item break @var{class}:@var{method} +Set a breakpoint in class @var{class} method @var{method}. You can +also use a period @code{.} instead of a colon @code{:}. Note that two +colons @code{::} are not used. Also note a class @emph{must} be +specified here. If the method you want to stop in is in the main class +(i.e. the class that @code{self} belongs to at the start of the +program), then use the name @code{Object}. + +@kindex catch @ovar{exception} @r{[} on | 1 | off | 0 @r{]} +@kindex cat @r{(@code{catch})} +@item catch @ovar{exception} @r{[} on | 1 | off | 0 @r{]} +Set catchpoint to an exception. Without an exception name show catchpoints. + +With an ``on'' or ``off'' parameter, turn handling the exception on or +off. To delete all exceptions type ``catch off''. + +@cindex delete breakpoints +@kindex delete @ovar{breakpoints} +@kindex del @r{(@code{delete})} +@item delete @ovar{breakpoints} +Delete the breakpoints specified as arguments. + +If no argument is specified, delete all breakpoints (@DBG asks +confirmation. You can abbreviate this command as @code{del}. +@kindex info breakpoints +@cindex @code{$_} and @code{info breakpoints} +@item info breakpoints @ovar{n} +@itemx info break @ovar{n} +Print a table of all breakpoints set and not deleted, with the +following columns for each breakpoint: + +@table @emph +@item Breakpoint Numbers (@samp{Num}) +@item Enabled or Disabled (@samp{Enb}) +Enabled breakpoints are marked with @samp{1}. @samp{0} marks breakpoints +that are disabled (not enabled). +@item File and Line (@samp{file:line}) +The filename and line number inside that file where of breakpoint in +the script. The file and line are separated with a colon. +@item Condition +A condition (an arithmetic expression) which when true causes the +breakpoint to take effect. +@end table +@noindent +If a breakpoint is conditional, @code{info break} shows the condition on +the line following the affected breakpoint; breakpoint commands, if any, +are listed after that. + +@code{info break} with a breakpoint number @var{n} as argument lists +only that breakpoint. + +Examples: +@example +(rdb:1) @b{info break} +Breakpoints at following places: +Num Enb What +1 y gcd.rb:3 +2 y gcb.rb:28 if n > 1 +(rdb:1) @b{info break 2} +2 y gcb.rb:28 if n > 1 +@end example +@end table + +@node Disabling +@subsection Disabling breakpoints (@samp{disable}, @samp{enable}) + +Rather than deleting a breakpoint, you might +prefer to @dfn{disable} it. This makes the breakpoint inoperative as if +it had been deleted, but remembers the information on the breakpoint so +that you can @dfn{enable} it again later. + +You disable and enable breakpoints and catchpoints with the +@code{enable} and @code{disable} commands, optionally specifying one +or more breakpoint numbers as arguments. Use @code{info break} to +print a list of breakpoints and catchpoints if you do not know which +numbers to use. + +A breakpoint or catchpoint can have any different +states of enablement: + +@itemize @bullet +@item +Enabled. The breakpoint stops your program. A breakpoint set +with the @code{break} command starts out in this state. +@item +Disabled. The breakpoint has no effect on your program. +@end itemize + +You can use the following commands to enable or disable breakpoints +and catchpoints: + +@table @code +@kindex disable breakpoints +@item disable @var{breakpoints} +Disable the specified breakpoints---or all breakpoints, if none are +listed. A disabled breakpoint has no effect but is not forgotten. All +options such as ignore-counts, conditions and commands are remembered in +case the breakpoint is enabled again later. You may abbreviate +@code{disable} as @code{dis}. + +@kindex enable breakpoints +@item enable @var{breakpoints} +Enable the specified breakpoints (or all defined breakpoints). They +become effective once again in stopping your program. + +@end table + +Breakpoints that you set are initially enabled; subsequently, they +become disabled or enabled only when you use one of the commands +above. (The command @code{until} can set and delete a breakpoint of +its own, but it does not change the state of your other breakpoints; +see @ref{Resuming Execution, ,Resuming Execution}.) + +@node Conditions +@subsection Break conditions (@samp{condition}) +@cindex conditional breakpoints +@cindex breakpoint conditions + +The simplest sort of breakpoint breaks every time your script reaches +a specified place. You can also specify a @dfn{condition} for a +breakpoint. A condition is just a Ruby expression. + +Break conditions can be specified when a breakpoint is set, by using +@samp{if} in the arguments to the @code{break} command. A breakpoint +with a condition evaluates the expression each time your script +reaches it, and your script stops only if the condition is +@emph{true}. They can also be changed at any time +with the @code{condition} command. + +@ifset FINISHED +You can also use the @code{if} keyword with the @code{watch} command. +The @code{catch} command does not recognize the @code{if} keyword; +@code{condition} is the only way to impose a further condition on a +catchpoint. +@end ifset + +@table @code +@kindex condition +@item condition @var{bnum} @var{expression} +Specify @var{expression} as the break condition for breakpoint +@var{bnum}. After you set a condition, breakpoint @var{bnum} stops +your program only if the value of @var{expression} is true (nonzero). + +@item condition @var{bnum} +Remove the condition from breakpoint number @var{bnum}. It becomes +an ordinary unconditional breakpoint. +@end table + +@ifset FINISHED +When you use @code{condition}, @DBG checks @var{expression} +immediately for syntactic correctness, and to determine whether +symbols in it have referents in the context of your breakpoint. If +@var{expression} uses symbols not referenced in the context of the +breakpoint, @DBG prints an error message: + +@example +No symbol "foo" in current context. +@end example +@end ifset + +@noindent +The debugger does not actually evaluate @var{expression} at the time +the @code{condition} command (or a command that sets a breakpoint with +a condition, like @code{break if @dots{}}) is given, however. + +Examples; +@example +condition 1 x>5 # Stop on breakpoint 0 only if x>5 is true. +condition 1 # Change that! Unconditionally stop on breakpoint 1. +@end example + +@node Resuming Execution +@subsection Resuming Execution (@samp{step}, @samp{next}, @samp{finish}, @samp{continue}) + +A typical technique for using stepping is to set a breakpoint +(@pxref{Breakpoints}) at the beginning of the function or the section +of your script where a problem is believed to lie, run your script +until it stops at that breakpoint, and then step through the suspect +area, examining the variables that are interesting, until you see the +problem happen. + +@cindex stepping +@cindex continuing +@cindex resuming execution +@dfn{Continuing} means resuming program execution until your script +completes normally. In contrast, @dfn{stepping} means executing just +one more ``step'' of your script, where ``step'' may mean either one +line of source code. Either when continuing or when stepping, +your script may stop even sooner, due to a breakpoint or a signal. + +@menu +* Step:: running the next statement (step) +* Next:: running the next statement skipping over functions (next) +* Finish:: running until the return of a function or ``source'' (finish) +* Continue:: continuing execution (continue) +@end menu + +@node Step +@subsubsection Step (@samp{step}) +@table @code +@kindex step @r{[}+@r{]} @ovar{count} +@kindex s @r{(@code{step})} +@item step @r{[}+-@r{]} @ovar{count} +Continue running your program until the next logical stopping point +and return control to @value{DBG}. This command is abbreviated +@code{s}. + +Like, the programming Lisp, Ruby tends implemented in a highly +expression-oriented manner. Therefore things that in other languages +that may appear to be a single statement are implemented in Ruby as +several expressions. For example, in an ``if'' statement or looping +statements a stop is made after the expression is evaluated but before +the test on the expression is made. + +So it is common that a lines in the program will have several stopping +points where in other debuggers of other languages there would be only +one. Or you may have several statements listed on a line. + +When stepping it is not uncommon to want to go to a different line on +each step. If you want to make sure that on a step you go to a +@emph{different} position, add a plus sign (@samp{+}). + +@emph{Note: step+ with a number count is not the same as issuing +count step+ commands. Instead it uses count-1 step commands followed +by a step+ command. For example, @code{step+ 3} is the +same as @code{step; step; step+}, not @code{step+; step+; step+}} + +If you find yourself generally wanting to use @code{step+} rather +than @code{step}, you may want to consider using @code{set +forcestep}, (@pxref{Forcestep}). + +If you have @code{forcestep} set on but want to temporarily disable it +for the next step command, append a minus, or @code{step-}. + +With a count, @code{step} will continue running as normal, but do so +@var{count} times. If a breakpoint is reached, or a signal not +related to stepping occurs before @var{count} steps, stepping stops +right away. +@end table + +@node Next +@subsubsection Next (@samp{next}) +@table @code +@kindex next @r{[}+-@r{]} @ovar{count} +@kindex n @r{(@code{next})} +@item next @r{[}+@r{]} @ovar{count} +This is similar to @code{step}, but function or method calls that +appear within the line of code are executed without stopping. As with +step, if you want to make sure that on a step you go to a +@emph{different} position, add a plus sign (@samp{+}). Similarly, +appending a minus disables a @code{forcestep} temporarily, and an +argument @var{count} is a repeat count, as for @code{step}. +@end table + +@node Finish +@subsubsection Finish (@samp{finish}) +@table @code +@kindex finish @ovar{frame-number} +@item finish @ovar{frame-number} +Execute until selected stack frame returns. If no frame number is +given, we run until the currently selected frame returns. The +currently selected frame starts out the most-recent frame or 0 if no +frame positioning (e.g@: @code{up}, @code{down} or @code{frame}) has +been performed. If a frame number is given we run until @var{frame} frames +returns. + +If you want instead to terminate the program and debugger entirely, +use @code{quit} (@pxref{Quitting the debugger, ,Quitting the debugger}). + +@emph{Note:} Releases before Ruby version 1.8.7 show the return line +as the first line of the method. Starting with version 1.8.7, the last +line executed will be shown as the return +line. @url{http://rubyforge.org/tracker/?func=detail&atid=22040&aid=18749&group_id=426} + +@end table + +@node Continue +@subsubsection Continue (@samp{continue}) +@table @code +@kindex continue @ovar{line-specification} +@kindex c @r{(@code{continue})} +@item continue @ovar{line-specification} +@itemx c @ovar{line-specification} +Resume program execution, at the address where your script last +stopped; any breakpoints set at that address are bypassed. + +The optional argument @var{line-specification} allows you to specify a +line number to set a one-time breakpoint which is deleted when that +breakpoint is reached. + +Should the program stop before that breakpoint is reached, for +example, perhaps another breakpoint is reached first, in +a listing of the breakpoints you won't see this entry in the list of +breakpoints. +@end table + +@node ruby-debug settings +@section ruby-debug settings (@samp{set args}, @samp{set autoeval}..) + +You can alter the way ruby-debug interacts with you using @code{set} +commands. + +The various parameters to @code{set} are given below. Each parameter +name needs to to be only enough to make it unique. For example +@code{set force} is a suitable abbreviation for @code{set forcestep}. +The letter case is not important, so @code{set FORCE} or @code{set +Force} are also suitable abbreviations. + +Many @code{set} commands are either ``on'' or ``off'', and you can +indicate which way you want set by supplying the corresponding +word. The number 1 can be used for ``on'' and 0 for ``off''. If none +of these is given, we will assume ``on''. A deprecated way of turning +something off is by prefacing it with ``no''. + +Each @code{set} command has a corresponding @code{show} command which +allows you to see the current value. + +@menu +* Args:: Annotation Level +* Autoeval:: Evaluate unrecognized commands +* Autolist:: Execute ``list'' command on every breakpoint +* Autoirb:: Invoke IRB on every stop +* Autoreload:: Reload source code when changed +* Basename:: Report file basename only showing file names +* Callstyle:: Show Report file basename only showing file names +* Forcestep:: Make sure 'next/step' commands always move to a new line +* Fullpath:: Display full file names in frames +* History:: Generic command for showing command history parameters. +* Keepframebindings:: Save frame binding on each call +* Linetrace:: line execution tracing +* Linetrace+:: line tracing style +* Listsize:: Number of lines to try to show in a 'list' command +* Post-mortem:: Whether post-mortem handling is in effect. +* Trace:: Display stack trace when 'eval' raises exception +* Width:: Number of characters the debugger thinks are in a line +@end menu + +@node Args +@subsection Set/Show args + +@table @code +@kindex set args @ovar{parameters} +@item set args @ovar{parameters} +Specify the arguments to be used if your program is rerun. If +@code{set args} has no arguments, @code{restart} executes your program +with no arguments. Once you have run your program with arguments, +using @code{set args} before the next @code{restart} is the only way to run +it again without arguments. + +@kindex show args +@item show args +Show the arguments to give your program when it is started. +@end table + +@node Autoeval +@subsection Set/Show auto-eval + +@table @code +@kindex set autoeval @r{[} on | 1 | off | 0 @r{]} +@item set autoeval @r{[} on | 1 | off | 0 @r{]} +Specify that debugger input that isn't recognized as a command should +be passed to Ruby for evaluation (using the current debugged program +namespace). Note however that we @emph{first} check input to see if it +is a debugger command and @emph{only} if it is not do we consider it +as Ruby code. This means for example that if you have variable called +@code{n} and you want to see its value, you could use @code{p n}, +because just entering @code{n} will be interpreted as the debugger +``next'' command. + +See also @ref{irb} and @ref{Autoirb}. + +When autoeval is set on, you'll get a different error message when you +invalid commands are encountered. Here's a session fragment to show +the difference +@smallexample +(rdb:1) @b{stepp} +Unknown command +(rdb:1) @b{set autoeval on} +autoeval is on. +(rdb:1) @b{stepp} +NameError Exception: undefined local variable or method `stepp' for ... +@end smallexample + +@kindex show autoeval +@item show args +Shows whether Ruby evaluation of debugger input should occur or not. +@end table + +@node Autolist +@subsection Execute ``list'' command on every breakpoint + +@node Autoirb +@subsection Set/Show auto-irb + +@table @code +@kindex set autoirb @r{[} on | 1 | off | 0 @r{]} +@item set autoirb @r{[} on | 1 | off | 0 @r{]} + +When your program stops, normally you go into a debugger command loop +looking for debugger commands. If instead you would like to directly +go into an irb shell, set this on. See also @ref{Autoeval} or +@ref{irb} if you tend to use debugger commands but still want Ruby +evaluation occasionally. + +@kindex show autoirb +@item show autoirb +Shows whether the debugger will go into irb on stop or not. +@end table + +@node Autoreload +@subsection Set/Show auto-reload +@table @code +@kindex set autoreload @r{[} on | 1 | off | 0 @r{]} +Set this on if the debugger should check to see if the source has +changed since the last time it reread in the file if it has. +@end table + +@node Basename +@subsection Set/Show basename + +@table @code +@kindex set basename @r{[} on | 1 | off | 0 @r{]} +@item set basename @r{[} on | 1 | off | 0 @r{]} +Source filenames are shown as the shorter ``basename'' +only. (Directory paths are omitted). This is useful in running the +regression tests and may useful in showing debugger examples as in +this text. You may also just want less verbose filename display. + +By default filenames are shown as with their full path. + +@kindex show basename +@item show basename +Shows the whether filename display shows just the file basename or not. +@end table + +@node Callstyle +@subsection Set/Show call style + +@table @code +@ifset FINISHED +@kindex set callstyle @r{[} short | last | tracked @r{]} +@item set forcestep @r{[} short | last | tracked @r{]} +@else +@kindex set callstyle @r{[} short | last +@item set forcestep @r{[} short | last +@end ifset + +Sets how you want call parameters displayed; @code{short} shows just +the parameter names; +@ifset FINISHED +@code{last} shows the parameter names and the +class of these variables as they currently exist. Note the type could +have changed between when the call and its current +values. +@end ifset +@code{tracked} is the most accurate but this adds +overhead. On every call, scalar values of the parameters get +saved. For non-scalar values the class is saved. +@end table + +@node Forcestep +@subsection Set/Show Forces Different Line Step/Next + +@table @code +@kindex set forcestep @r{[} on | 1 | off | 0 @r{]} +@item set forcestep @r{[} on | 1 | off | 0 @r{]} + +Due to the interpretive, expression-oriented nature of the Ruby +Language and implementation, each line often contains many possible +stopping points, while in a debugger it is often desired to treat each +line as an individual stepping unit. + +Setting forcestep on will cause each @code{step} or @code{next} +command to stop at a different line number. See also @ref{Step} and +@ref{Next}. + +@kindex show forcestep +@item show forcestep +Shows whether forcestep is in effect or not. +@end table + +@node Fullpath +@subsection Set/Show Frame full path + +@node History +@subsection Command History Parameters +@table @code +@item show commands +@kindex show commands +Display the last ten commands in the command history. + +@item show commands @var{n} +@kindex show commands @var{n} +Print ten commands centered on command number @var{n}. + +@item show history filename +@kindex show history filename +Show the filename in which to record the command history +(the list of previous commands of which a record is kept). + +@item set history save @r{[} on | 1 | off | 0 @r{]} +@kindex set history save @r{[} on | 1 | off | 0 @r{]} +Set whether to save the history on exit. + +@item show history save +@kindex show history save +Show saving of the history record on exit. + +@item set history size @var{number} +@kindex set history size @var{number} +Set the maximum number of commands to save in the history. + +@item show history size +@kindex show history size +Show the size of the command history, i.e. the number of previous +commands to keep a record of. +@end table + +@node Keepframebindings +@subsection Save frame binding on each call + +@node Linetrace +@subsection Set/Show Line tracing + +@table @code +@kindex set linetrace @r{[} on | 1 | off | 0 @r{]} +@item set linetrace @r{[} on | 1 | off | 0 @r{]} + +Setting linetrace on will cause lines to be shown before run. + +@kindex show linetrace +@item show linetrace +Shows whether line tracing is in effect or not. +@end table + +@node Linetrace+ +@subsection Set/Show Line tracing style + +@table @code +@kindex set linetrace+ @r{[} on | 1 | off | 0 @r{]} +@item set linetrace+ @r{[} on | 1 | off | 0 @r{]} + +Setting linetrace+ on will cause consecutive trace lines not to be a +duplicate of the preceding line-trace line. Note however that this +setting doesn't by itself turn on or off line tracing. + +@kindex show linetrace+ +@item show linetrace +Shows whether the line tracing style is to show all lines or remove +duplicates linetrace lines when it is a repeat of the previous line. +@end table + +@node Listsize +@subsection Set/Show lines in a List command + +@table @code +@kindex set listsize @var{number-of-lines} +@item set listsize @var{number-of-lines} +Set number of lines to try to show in a @code{list} command. +@kindex show listsize +@item show listsize +Shows the list-size setting. +@end table + +@node Post-mortem +@subsection Show Post-mortem handling +@table @code +@kindex show post-mortem +Shows wither post-mortem debugging is in effect. Right now we don't +have the ability to change the state inside the debugger. +@end table + +@node Trace +@subsection Display stack trace when 'eval' raises exception + +@node Width +@subsection Set/Show Line width + +@table @code +@kindex set width @var{column-width} +@item set width @var{column-width} +Set number of characters the debugger thinks are in a line. +We also change OS environment variable @code{COLUMNS}. +@kindex show width +@item show width +Shows the current width setting. +@end table + +@node Program Information +@section Program Information (@samp{info}) + +This @code{info} command (abbreviated @code{i}) is for describing the +state of your program. For example, you can list the current +parameters with @code{info args}, or list the breakpoints you have set +with @code{info breakpoints} or @code{info watchpoints}. You can get +a complete list of the @code{info} sub-commands with @w{@code{help +info}}. + +@table @code +@kindex info args + +@item info args +Method arguments of the current stack frame. +@kindex info breakpoints + +@item info breakpoints +Status of user-settable breakpoints +@kindex info display + +@item info display +All display expressions. +@kindex info files + +@item info files +Source files in the program. +@kindex info file + +@item info file @var{filename} @ovar{all|lines|mtime|sha1} +Information about a specific file. Parameter @code{lines} gives the +number of lines in the file, @code{mtime} shows the modification time +of the file (if available), @code{sha1} computes a SHA1 has of the +data of the file. @code{all} gives all of the above information. + +@kindex info line +@item info line +Line number and file name of current position in source. +@kindex info locals +@item info locals +Local variables of the current stack frame. +@kindex info program +@item info program +Display information about the status of your program: whether it is +running or not and why it stopped. If an unhandled exception occurred, +the exception class and @code{to_s} method is called. +@kindex info stack +@item info stack +Backtrace of the stack. An alias for @code{where}. @xref{Backtrace}. +@kindex info thread +@item info thread @ovar{thread-number} @r{[} terse | verbose@r{]} +If no thread number is given, we list info for all +threads. @code{terse} and @code{verbose} options are possible. If terse, +just give summary thread name information. See information under @code{info threads} for +more detail about this summary information. + +If @code{verbose} is appended to the end of the command, then the entire +stack trace is given for each thread. + +@kindex info threads @r{[} terse | verbose@r{]} +@item info threads + +List information about currently-known threads. This information +includes whether the thread is current (+), if it is suspended ($), or +ignored (!); the thread number and the top stack item. If +@code{verbose} is given then the entire stack frame is shown. Here is +an example: + +@smallexample +(rdb:7) info threads + 1 # ./test/thread1.rb:27 + !2 # + 3 # ./test/thread1.rb:11 + 4 # ./test/thread1.rb:11 + 5 # ./test/thread1.rb:11 + 6 # ./test/thread1.rb:11 ++ 7 # ./test/thread1.rb:14 +(rdb:1) +@end smallexample + +Thread 7 is the current thread since it has a plus sign in front. Thread 2 is +ignored since it has a @code{!}. A ``verbose'' listing of the above: + +@smallexample +(rdb:7) info threads verbose + 1 # + #0 Integer.join at line test/thread1.rb:27 + #1 at line test/thread1.rb:27 + !2 # + 3 # + #0 sleep(count#Fixnum) at line test/thread1.rb:11 + #1 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:11 + #2 at line test/thread1.rb:23 + 4 # + #0 sleep(count#Fixnum) at line test/thread1.rb:11 + #1 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:11 + #2 at line test/thread1.rb:23 + 5 # + #0 sleep(count#Fixnum) at line test/thread1.rb:11 + #1 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:11 + #2 at line test/thread1.rb:23 + 6 # + #0 sleep(count#Fixnum) at line test/thread1.rb:11 + #1 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:11 + #2 at line test/thread1.rb:23 ++ 7 # + #0 Object.fn(count#Fixnum, i#Fixnum) at line test/thread1.rb:14 + #1 at line test/thread1.rb:23 +@end smallexample + +@kindex info variables +@item info variables +Local and instance variables. +@end table + +@node Post-Mortem Debugging +@chapter Post-Mortem Debugging +@cindex post-mortem debugging + +It is also to possible enter the debugger when you have an uncaught +exception that is about to terminate our program. This is called +@emph{post-mortem debugging}. In this state many, of the debugger commands +for examining variables and moving around in the stack still +work. However some commands, such as those which imply a continuation +of running code, no longer work. + +The most reliable way to set up post-mortem debugging is to use the +@option{--post-mortem} option in invoking @code{rdebug}. See @ref{rdebug +command-line options}. This traps/wraps at the debugger ``load'' of +your Ruby script. When this is done, your program is stopped after +the exception takes place, but before the stack has been +unraveled. (Alas, it would be nice to if one could allow resetting the +exception and continuing, but details of code in Ruby 1.8's +@code{eval.c} prevent this.) + +If however you haven't invoked @code{rdebug} at the outset, but +instead call @code{ruby-debug} from inside your program, to set up +post-mortem debugging set the @code{post_mortem} key in +@code{Debugger.start}. Here's an example modified from +@url{http://www.datanoise.com/articles/2006/12/20/post-mortem-debugging}: + +@smallexample + $ @b{cat t.rb } + require 'rubygems' + require 'ruby-debug' ; Debugger.start(:post_mortem => true) + + def t1 + raise 'test' + end + def t2 + t1 + end + t2 + + $ @b{ruby t.rb } + t.rb:8: raise 'test' + (rdb:post-mortem) @b{l=} + [3, 12] in t.rb + 3 + 4 Debugger.start + 5 Debugger.post_mortem + 6 + 7 def t1 + => 8 raise 'test' + 9 end + 10 def t2 + 11 t1 + 12 end + (rdb:post-mortem) +@end smallexample + +Alternatively you can call @code{Debugger.post_mortem()} after rdebug has +been started. The @code{post_mortem()} method can be called in two +ways. Called without a block, it installs a global @code{at_exit()} hook +that intercepts exceptions not handled by your Ruby script. In +contrast to using the @option{--post-mortem} option, when this hook +occurs after the call stack has been rolled back. (I'm not sure if +this in fact makes any difference operationally; I'm just stating it +because that's how it works.) + +If you know that a particular block of code raises an exception you +can enable post-mortem mode by wrapping this block inside a +@code{Debugger.post_mortem} block + +@smallexample +def offender + 1/0 +end +... +require "ruby-gems" +require "ruby-debug" +Debugger.post_mortem do + ... + offender + ... +end +@end smallexample + +Once inside the debugger in post-mortem debugging, the prompt should +be @code{(rdb:post-mortem)}. + +@node Debugger Module and Class +@chapter The Debugger Module and Class + +@menu +* Debugger Module:: ruby-debug's Debugger module +* Debugger Class:: Debugger class +* Kernel routines:: Routines added to Kernel +@end menu + +@node Debugger Module +@section The Debugger Module + +@menu +* Debugger.run:: +@ifset LATER +* Debugger.post-mortem:: +@end ifset +* Debugger.context:: +* Debugger.settings:: +@end menu + +@node Debugger.run +@subsection @code{Debugger.start}, @code{Debugger.started?}, @code{Debugger.stop}, @code{Debugger.run_script} + +In order to provide better debugging information regarding the stack +frame(s) across all threads, ruby-debug has to intercept each call, +save some information and on return remove it. Possibly, in Ruby 1.9 +possibly this will not be needed. Therefore one has to issue call to +indicate start saving information and another call to stop. Of course, +If you call ruby-debug from the outset via @code{rdebug} this is done +for you. + +@table @code +@item Debugger.start(@ovar{options}) @ovar{block} +@vindex @code{Debugger.start(options)} +@vindex @code{Debugger.start(block)} +Turn on add additional instrumentation code to facilitate debugging. A +system even table hook is installed and some variables are set up to +access thread frames. + +This needs to be done before entering the debugger; therefore a call +to the debugger issue a @code{Debugger.start} call if necessary. + +If called without a block, @code{Debugger.start} returns @code{true} if +the debugger was already started. But if you want to know if the +debugger has already been started @code{Debugger.started?} can tell +you. + +If a block is given, the debugger is started and @code{yields} to +block. When the block is finished executing, the debugger stopped with +the @code{Debugger.stop method}. You will probably want to put a call +to @code{debugger} somwhere inside that block + +But if you want to completely stop debugger, you must call +@code{Debugger.stop} as many times as you called Debugger.start +method. + +The first time Debugger.start is called there is also some additional +setup to make the @code{restart} command work. In particular, @code{$0} and +@code{ARGV} are used to set internal debugger variables. + +Therefore you should make try to make sure that when +@code{Debugger.start} is called neither of these variables has been +modified. If instead you don't want this behavior you can pass an +options has and set the @code{:init} key to @code{false}. That is +@smallexample + Debugger.start(:init => false) # or Debugger.start(@{:init => false@}) +@end smallexample + +If you want post-mortem debugging, you can also supply +@code{:post_mortem => true} in @code{Debugger.start}. + +@item Debugger.started? +@vindex @code{Debugger.started?} +Boolean. Return @code{true} if debugger has been started. + +@item Debugger.stop +@vindex @code{Debugger.stop} +Turn off instrumentation to allow debugging. Return @code{true} is returned +if the debugger is disabled, otherwise it returns @code{false}. +@emph{Note that if you want to stop debugger, you must call Debugger.stop +as many times as you called the @code{Debugger.start} method.} + +@item Debugger.run_script(@var{debugger-command-file}, out = handler.interface) +@vindex @code{Debugger.run_script} +Reads/runs the given file containing debugger commands. @code{.rdebugrc} is run this way. + +@item Debugger.last_exception +@vindex @code{Debugger.last_exception} +If not @code{nil}, this contains @code{$!} from the last exception. + +@end table + +@node Debugger.context +@subsection @code{Debugger.context} +As mentioned previously, @code{Debugger.start} instruments additional +information to be obtained about the current block/frame stack. Here +we describe these additional @code{Debugger.context} methods. + +Were a frame position is indicated, it is optional. The top or current frame +position (position zero) is used if none is given. + +@table @code +@item Debugger.context.frame_args @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_args} +If track_frame_args? is true, return information saved about call +arguments (if any saved) for the given frame position. + +@item Debugger.context.frame_args_info @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_args_info} + +@item Debugger.context.frame_class @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_args_info} +Return the class of the current frame stack. + +@item Debugger.context.frame_file @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_file} +Return the filename of the location of the indicated frame position. + +@item Debugger.context.frame_id @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_id} +Same as @code{Debugger.context.method}. + +@item Debugger.context.frame_line @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_line} +Return the filename of the location of the indicated frame position. + +@item Debugger.context.frame_method @ovar{frame-position=0} +@vindex @code{Debugger.context.frame_method} +Symbol of the method name of the indicated frame position. + +@item Debugger.context.stack_size +@vindex @code{Debugger.context.stack_size} +Return the number the size of the frame stack. Note this may be less +that the actual frame stack size if debugger recording +(@code{Debugger.start}) was turned on at after some blocks were added +and not finished when the @code{Debugger.start} was issued. +@end table + +@node Debugger.settings +@subsection @code{Debugger.settings} +@vindex @code{Debugger.settings} +Symbols listed here are keys into the Array @code{Debugger.settings}. +These can be set any time after the @code{ruby-debug} is loaded. For example: +@smallexample + require "ruby-debug/debugger" + Debugger.settings[:autoeval] = true # try eval on unknown debugger commands + Debugger.listsize = 20 # Show 20 lines in a list command +@end smallexample + +@table @code +@item :argv +Array of String. @code{argv[0]} is the debugged program name and +@code{argv[1..-1]} are the command arguments to it. +@item :autoeval +Boolean. True if auto autoeval on. @xref{Autoeval}. +@item :autoirb +Fixnum: 1 if on or 0 if off. @xref{Autoirb}. +@item :autolist +Fixnum: 1 if on or 0 if off. +@item :basename +Boolean. True if basename on. @xref{Basename}. +@item :callstyle +Symbol: @code{:short} or @code{:last}. @xref{Callstyle}. +@item :debuggertesting +Boolean. True if currently testing the debugger. +@item :force_stepping +Boolean. True if stepping should go to a line different from the last +step. @xref{Forcestep}. +@item :full_path +Boolean. @xref{Fullpath}. +@item :listsize +Fixnum. Number of lines to show in a @code{list} command. @xref{Listsize}. +@item :reload_source_on_change +Boolean. True if we should reread the source every time it changes. @xref{Autoreload}. +@item :stack_trace_on_error +Boolean. True if we should produce a stack trace on error. @xref{Trace}. +@item :width +Fixnum. Number of characters the debugger thinks are in a line. @xref{Width}. +@end table + +@node Debugger Class +@section The @code{Debugger} Class +@menu +* Debugger.Breakpoint:: Debugger::Breakpoint +* Debugger.Context:: Debugger::Context +* Debugger.Command:: Debugger::Command +@end menu + +@table @code +@item add_breakpoint(file, line, expr) +@vindex @code{Debugger.add_breakpoint} +Adds a breakpoint in file @var{file}, at line @var{line}. If +@var{expr} is not nil, it is evaluated and a breakpoint takes effect +at the indicated position when that expression is true. You should +verify that @var{expr} is syntactically valid or a @code{SyntaxError} +exception, and unless your code handles this the debugged program may +terminate. + +@item remove_breakpoint(bpnum) +@vindex @code{Debugger.remove_breakpoint} +When a breakpoint is added, it is assigned a number as a way to +uniquely identify it. (There can be more than one breakpoint on a +given line.) To remove a breakpoint, use @code{remove_breakpoint} with +breakpoint number @var{bpnum}. + +@item breakpoints +@vindex @code{Debugger.breakpoints} +Return a list of the breakpoints that have been added but not removed. +@end table + +@node Debugger.Breakpoint +@subsection The @code{Debugger::Breakpoint} Class +Breakpoint are objects in the @code{Debugger::Breakpoint} class. +@table @code +@item enabled? +@vindex @code{Debugger::Breakpoints.enabled?} +Returns whether breakpoint is enabled or not. + +@item enabled= +@vindex @code{Debugger::Breakpoints.enabled=} +Sets whether breakpoint is enabled or not. + +@item expr +@vindex @code{Debugger::Breakpoints.expr} +Expression which has to be true at the point where the breakpoint is +set before we stop. + +@item expr= +@vindex @code{Debugger::Breakpoints.expr=} + +@item hit_condition +@item hit_condition= +@vindex @code{Debugger::Breakpoints.condition} +@vindex @code{Debugger::Breakpoints.condition=} + +@item hit_count +@vindex @code{Debugger::Breakpoints.hit_count} +Returns the hit count of the breakpoint. + +@item hit_value +@vindex @code{Debugger::Breakpoints.hit_value} +Returns the hit value of the breakpoint. + +@item hit_value= +@vindex @code{Debugger::Breakpoints.hit_value=} +Sets the hit value of the breakpoint. + +@item id +@cindex @code{Debugger::Breakpoints.id} +A numeric name for the breakpoint which is used in listing breakpoints +and removing, enabling or disabling the breakpoint + +@item pos +@vindex @code{Debugger::Breakpoints.pos=} +Returns the line number of this breakpoint. +@item pos= +@vindex @code{Debugger::Breakpoints.pos=} +Sets the line number of this breakpoint. + +@item source +@vindex @code{Debugger::Breakpoints.source} +Returns the file name in which the breakpoint occurs. + +@item source= +@vindex @code{Debugger::Breakpoints.source=} +Sets the file name in which the breakpoint occurs. +@end table + +@node Debugger.Context +@subsection The @code{Debugger::Context} Class +Callbacks in @code{Debugger:Context} get called when a stopping point +or an event is reached. It has information about the suspended program +which enable a debugger to inspect the frame stack, evaluate variables +from the perspective of the debugged program, and contains information +about the place the debugged program is stopped. + +@table @code +@item at_line(@var{file}, @var{line}) +@vindex Debugger::Context::at_line(@var{file}, @var{line}) +This routine is called when the debugger encounters a ``line'' event for +which it has been indicated we want to stop at, such as by hitting a +breakpoint or by some sort of stepping. + +@item at_return(@var{file}, @var{line}) +@vindex Debugger::Context::at_return(@var{file}, @var{line}) +This routine is called when the debugger encounters a ``return'' event for +which it has been indicated we want to stop at, such as by hitting a +@code{finish} statement. + +@item debug_load(@var{file}, @var{stop-initially}) +@vindex Debugger::Context::debug_load(@var{file}, @var{stop-initially}) +This method should be used to debug a file. If the file terminates +normally, @code{nil} is returned. If not a backtrace is returned. + +The @var{stop-initially} parameter indicates whether the program +should stop after loading. If an explicit call to the debugger is in +the debugged program, you may want to set this @code{false}. +@end table + +@node Debugger.Command +@subsection The @code{Debugger::Command} Class + +Each command you run is in fact its own class. Should you want to extend +ruby-debug, it's pretty easy to do since after all ruby-debug is Ruby. + +Each @code{Debugger#Command} class should have the a @code{regexp} +method. This method returns regular expression for command-line +strings that match your command. It's up to you to make sure this +regular expression doesn't conflict with another one. If it does, it's +undefined which one will get matched and run + +In addition the instance needs these methods: +@table @code +@item execute +Code which gets run when you type a command (string) that matches the +commands regular expression. +@item help +A string which gets displayed when folks as for help on that command +@item help_command +A name used the help system uses to show what commands are available. +@end table + +Here's a small example of a new command: +@smallexample +module Debugger + class MyCommand < Command + def regexp + /^\s*me$/ # Regexp that will match your command + end + + def execute + puts "hi" # What you want to happen when your command runs + end + class << self + def help_command + 'me' # String name of command + end + def help(cmd) + # Some sort of help text. + %@{This does whatever it is I want to do@} + end + end +end +@end smallexample + +Now here's an example of how you can load/use it: +@smallexample + require 'rubygems' + require 'ruby-debug' + require '/tmp/mycmd.rb' # or wherever + Debugger.start + x=1 + debugger + y=2 +@end smallexample + +And now an example of invoking it: +@smallexample +ruby /tmp/testit.rb: +/tmp/testit.rb:7 +y=2 +(rdb:1) help +ruby-debug help v0.10.3 +Type 'help ' for help on a specific command +Available commands: +backtrace delete enable help method putl set trace +break disable eval info next quit show undisplay +catch display exit irb p reload source up +condition down finish list pp restart step var +continue edit frame me ps save thread where + ^^ This is you + +(rdb:1) help me +This does whatever it is I want to do +(rdb:1) me +hi +(rdb:1) +@end smallexample + +@node Kernel routines +@section Additions to @code{Kernel} + +@table @code + +@item debugger @ovar{steps=1} +@vindex @code{Kernel::debugger} +Enters the debugger in the current thread after a stepping @var{steps} line-event steps. +Before entering the debugger startup script is read. + +Setting @var{steps} to 0 will cause a break in the debugger subroutine +and not wait for eany line event to occur. This could be useful you +want to stop right after the last statement in some scope. + +Consider this example: +@smallexample +$ cat scope-test.rb + +require 'rubygems' +require 'ruby-debug' ; Debugger.start +1.times do + a = 1 + debugger # implied steps=1 + end +y = 1 + +$ scope-test.rb:8 +y = 1 +(rdb:1) p a +NameError Exception: undefined local variable or method `a' for main:Object +(rdb:1) +@end smallexample +The debugger will get at the line event which follows @samp{a=1}. This +is outside the @code{do} block scope where @var{a} is defined. If +instead you want to stop before leaving the @code{do} loop it is +possibly to stop right inside the @code{debugger}; call with 0 zero parameter: +@smallexample +$ cat scope-test.rb + +require 'rubygems' +require 'ruby-debug' ; Debugger.start +1.times do + a = 1 + debugger(0) +end +y = 1 + +$ scope-test.rb:8 +../lib/ruby-debug-base.rb:175 +Debugger.current_context.stop_frame = 0 +(rdb:1) where +--> #0 Kernel.debugger(steps#Fixnum) at line ../lib/ruby-debug-base.rb:175 + #1 at line scope-test.rb:6 + #2 at line scope-test.rb:4 +(rdb:1) up +#1 at line scope-test.rb:6 +(rdb:1) p a +1 +(rdb:1) +@end smallexample +As seen above you will have to position the frame up one to be back in +your debugged program rather than in the debugger. + +@item breakpoint @ovar{steps=1} +@vindex @code{Kernel::breakpoint} +An alias for debugger. + +@item binding_n @ovar{n=0} +@vindex @code{Kernel::binding_n} +Returns a @samp{binding()} for the @var{n}-th call frame. Note however +that you need to first call @samp{Debugger.start} before issuing this +call. + +@end table + +@node Using from Subversion +@appendix Building and Installing from rubyforge's Subversion Repository + +Here are Unix-centric instructions. If you have Microsoft Windows or +OSX some of the below may need adjusting. + +@menu +* Prerequisites:: +* Package Checkout:: +* Trying Out:: +* Running Regression Tests:: +* Building the Documentation and Emacs files:: +* Building for Microsoft Windows:: +@end menu + +@node Prerequisites +@section Prerequisites: To build the package you'll need at a minimum: + +@itemize @bullet +@item +Ruby (of course). Currently only version 1.8.6 and above but not +version 1.9.@emph{x} work. +@item +Ruby development headers. This typically includes a file called @file{ruby.h} +@item +A C compiler like GNU C (@code{gcc}) +@item +Rake +@item +Subversion (@code{svn}). +@end itemize + +If you want to build the documentation and install Emacs files, you'll +also need: + +@itemize @bullet +@item + a POSIX shell like bash +@item + autoconf +@item + automake +@item + GNU Make +@item + texinfo +@end itemize + +@node Package Checkout +@section Basic Package Checkout and Installation + +Check out the trunk of repository following the instructions at +@url{http://rubyforge.org/scm/?group_id=1900} For example on a Unixy system, +this may work: + +@smallexample + mkdir ruby-debug + cd ruby-debug + svn checkout svn://rubyforge.org/var/svn/ruby-debug/trunk trunk +@end smallexample + +In order to make the Ruby gems, @code{ruby-debug} and +@code{ruby-debug-base}, get yourself into the trunk directory after +the code has been checked out and run: + +@smallexample + cd trunk # This is the same trunk checked out above. + rake package +@end smallexample + +If all goes well you should have some gem files put in the directory +@code{pkg}. Use the gem command to install that. + +@smallexample + sudo gem install ruby-debug-*.gem # See gem help for other possibilities +@end smallexample + +If all goes well the rdebug script has been installed ruby-debug is +now ready to run. But if everything goes well you might want to run +the built-in regression tests to make sure everything is okay. +See step 3 below. + +If the gem install didn't work,'t there may be a problem with your C +compiler or the Ruby headers are not installed. + +@node Trying Out +@section Trying Out without Installing + +You don't have to build a gem file to try out ruby debug. In fact when +developing new features for ruby-debug, developers often you want to +try it out @emph{before} installing. If you have a problem in the latter +part of step 1 you may want to try this approach since we go into a +little more detail as to what happens under the covers when you do the +gem install. + +Run (from trunk) +@smallexample + rake lib +@end smallexample + +This creates a Makefile and builds the ruby-debug shared library. (On +Unix the name is @code{ruby_debug.so}). + +Once this is done you can run the debugger as you would rdebug using the +script @code{runner.sh}. For example (again from trunk) + +@smallexample + ./runner.sh ~/my-ruby-program.rb +@end smallexample + +@node Running Regression Tests +@section Running the Regression Tests + +We've put together some basic tests to make sure ruby-debug is doing +what we think it should do. To run these (from @code{trunk}): + +@smallexample + rake test +@end smallexample + +If you didn't build the ruby-debug shared library and skipped step 2, +don't worry @code{rake test} will do step 2 for you. You should see a +line that ends something like: + +@smallexample + Finished in 2.767579 seconds. + + 12 tests, 35 assertions, 0 failures, 0 errors +@end smallexample + +The number of seconds, tests, and assertions may be different from the +above. However you @emph{should} see exactly ``0 failures, 0 errors.'' + +@node Building the Documentation and Emacs files +@section Building the Documentation and Testing/Installing Emacs Files + +Of course, I recommend you read the ruby-debug manual that comes with +the package. If you have the prerequisites described above, run this +once: +@smallexample + sh ./autogen.sh +@end smallexample + +Then run: +@smallexample + ./configure + make + make test # Runs Emacs regression tests + sudo make install # Or arrange to do this as root +@end smallexample + +@node Building for Microsoft Windows +@section Building for Microsoft Windows + +Microsoft Windows is ``special'' and building @code{ruby-debug-base} +on it requires extra care. A problem here seems to be that the +``One-click'' install is compiled using Microsoft Visual Studio C, version 6 +which is not sold anymore and is rather old. + +Instead I suggest building via mingw/msys. +@url{http://eigenclass.org/hiki.rb?cmd=view&p=cross+compiling+rcovrt&key=mingw} +has instructions on how to do. Some amendments to these instructions. + +First, those instructions are a little GNU/Linux centric. If you are +using Ubuntu or Debian, then this should be the easiest to follow the +instructions. On Ubuntu or Debian there is a mingw3 Debian +package. Installing that will give you the cross compiler that is a +prerequisite. Alternatively if you are running MS Windows I notice +that cygwin also has a mingw package. Or possibly you could use MinGW +directly. For other OS's you might have to build a cross-compiler, +i.e. gcc which emits win32 code and can create a win32 DLL. + +After you have a cross compiler you need to download the Ruby source +and basically build a ruby interpreter. The cross-compile.sh script +works although when I downloaded it, it had lots of blank space at the +beginning which will mess up the Unix magic interpretation. That is +remove the blanks in front of @code{#/bin/sh}. + +On my system, this script fails in running @code{make ruby} because the +fake.rb that got created needed to have a small change: + +@smallexample + + ALT_SEPARATOR = "\"; \ +@end smallexample +should be: +@smallexample + ALT_SEPARATOR = "\\"; \ +@end smallexample + +After fixing this, run @code{make ruby}. Also, I needed to run +@code{make rubyw}. + +And then @code{make install} as indicated. + +Once all of that's in place, the place you want be is in +@code{ruby-debug/trunk/ext/win32}, not @code{ruby-debug/ext}. + +So let's say you've installed the cross-compiled install ruby in +@code{/usr/local/ruby-mingw32/}. Here then are the commands to build @code{ruby-debug-base-}@emph{xxx}@code{-mswin32.gem}: +@smallexample + cd .../ruby-debug/trunk/ext/win32 + ruby -I /usr/local/ruby-mingw32/lib/ruby/1.8/i386-mingw32 ../extconf.rb + make # Not rake + cd ../.. # back in ruby-debug/trunk + rake win32_gem +@end smallexample + +@node Class Module Index +@unnumbered Class, Module Method Index +@printindex vr + +@node Command Index +@unnumbered Command Index +@printindex ky + +@node General Index +@unnumbered General Index +@printindex cp + +@tex +% I think something like @colophon should be in texinfo. In the +% meantime: +\long\def\colophon{\hbox to0pt{}\vfill +\centerline{The body of this manual is set in} +\centerline{\fontname\tenrm,} +\centerline{with headings in {\bf\fontname\tenbf}} +\centerline{and examples in {\tt\fontname\tentt}.} +\centerline{{\it\fontname\tenit\/},} +\centerline{{\bf\fontname\tenbf}, and} +\centerline{{\sl\fontname\tensl\/}} +\centerline{are used for emphasis.}\vfill} +\page\colophon +% Blame: doc@cygnus.com, 1991. +@end tex + +@bye diff --git a/doc/test-tri2.rb b/doc/test-tri2.rb new file mode 100644 index 0000000..2be90bc --- /dev/null +++ b/doc/test-tri2.rb @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby +require "test/unit" +require "tri2.rb" +require "rubygems" +require "ruby-debug" +Debugger.start + +class TestTri < Test::Unit::TestCase + def test_basic + debugger + solutions = [] + 0.upto(5) do |i| + solutions << triangle(i) + end + assert_equal([0, 1, 3, 6, 10, 15], solutions, + "Testing the first 5 triangle numbers") + end +end diff --git a/doc/tri3.rb b/doc/tri3.rb new file mode 100644 index 0000000..0564847 --- /dev/null +++ b/doc/tri3.rb @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +def triangle(n) + (0..n).inject do |sum, i| + sum +=i + end +end +puts triangle(3) + diff --git a/doc/triangle.rb b/doc/triangle.rb new file mode 100644 index 0000000..39f038c --- /dev/null +++ b/doc/triangle.rb @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +# Compute the n'th triangle number - the hard way +# triangle(n) == (n * (n+1)) / 2 +def triangle(n) + tri = 0 + 0.upto(n) do |i| + tri += i + end + return tri + end + +puts triangle(3) diff --git a/emacs/.svn/README.txt b/emacs/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/emacs/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/emacs/.svn/dir-prop-base b/emacs/.svn/dir-prop-base new file mode 100644 index 0000000..f28ed7f --- /dev/null +++ b/emacs/.svn/dir-prop-base @@ -0,0 +1,10 @@ +K 10 +svn:ignore +V 48 +.cvsignore +*.elc +Makefile.in +elc-stamp +Makefile + +END diff --git a/emacs/.svn/dir-props b/emacs/.svn/dir-props new file mode 100644 index 0000000..f28ed7f --- /dev/null +++ b/emacs/.svn/dir-props @@ -0,0 +1,10 @@ +K 10 +svn:ignore +V 48 +.cvsignore +*.elc +Makefile.in +elc-stamp +Makefile + +END diff --git a/emacs/.svn/empty-file b/emacs/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/emacs/.svn/entries b/emacs/.svn/entries new file mode 100644 index 0000000..2d9dc45 --- /dev/null +++ b/emacs/.svn/entries @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/emacs/.svn/format b/emacs/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/emacs/.svn/format @@ -0,0 +1 @@ +4 diff --git a/emacs/.svn/prop-base/Makefile.am.svn-base b/emacs/.svn/prop-base/Makefile.am.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/.svn/prop-base/Makefile.am.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/.svn/prop-base/rdebug-annotate.el.svn-base b/emacs/.svn/prop-base/rdebug-annotate.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-annotate.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-breaks.el.svn-base b/emacs/.svn/prop-base/rdebug-breaks.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-breaks.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-cmd.el.svn-base b/emacs/.svn/prop-base/rdebug-cmd.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-cmd.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-core.el.svn-base b/emacs/.svn/prop-base/rdebug-core.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-core.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-dbg.el.svn-base b/emacs/.svn/prop-base/rdebug-dbg.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-dbg.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-error.el.svn-base b/emacs/.svn/prop-base/rdebug-error.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-error.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-fns.el.svn-base b/emacs/.svn/prop-base/rdebug-fns.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-fns.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/.svn/prop-base/rdebug-frames.el.svn-base b/emacs/.svn/prop-base/rdebug-frames.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-frames.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-gud.el.svn-base b/emacs/.svn/prop-base/rdebug-gud.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-gud.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-help.el.svn-base b/emacs/.svn/prop-base/rdebug-help.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-help.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-info.el.svn-base b/emacs/.svn/prop-base/rdebug-info.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-info.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/.svn/prop-base/rdebug-layouts.el.svn-base b/emacs/.svn/prop-base/rdebug-layouts.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-layouts.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-locring.el.svn-base b/emacs/.svn/prop-base/rdebug-locring.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-locring.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-output.el.svn-base b/emacs/.svn/prop-base/rdebug-output.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-output.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-regexp.el.svn-base b/emacs/.svn/prop-base/rdebug-regexp.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-regexp.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-secondary.el.svn-base b/emacs/.svn/prop-base/rdebug-secondary.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-secondary.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-shortkey.el.svn-base b/emacs/.svn/prop-base/rdebug-shortkey.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-shortkey.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-source.el.svn-base b/emacs/.svn/prop-base/rdebug-source.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-source.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-track.el.svn-base b/emacs/.svn/prop-base/rdebug-track.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-track.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-varbuf.el.svn-base b/emacs/.svn/prop-base/rdebug-varbuf.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-varbuf.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-vars.el.svn-base b/emacs/.svn/prop-base/rdebug-vars.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-vars.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug-watch.el.svn-base b/emacs/.svn/prop-base/rdebug-watch.el.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/prop-base/rdebug-watch.el.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/prop-base/rdebug.el.svn-base b/emacs/.svn/prop-base/rdebug.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/.svn/prop-base/rdebug.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/.svn/props/Makefile.am.svn-work b/emacs/.svn/props/Makefile.am.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/.svn/props/Makefile.am.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/.svn/props/rdebug-annotate.el.svn-work b/emacs/.svn/props/rdebug-annotate.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-annotate.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-breaks.el.svn-work b/emacs/.svn/props/rdebug-breaks.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-breaks.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-cmd.el.svn-work b/emacs/.svn/props/rdebug-cmd.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-cmd.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-core.el.svn-work b/emacs/.svn/props/rdebug-core.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-core.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-dbg.el.svn-work b/emacs/.svn/props/rdebug-dbg.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-dbg.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-error.el.svn-work b/emacs/.svn/props/rdebug-error.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-error.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-fns.el.svn-work b/emacs/.svn/props/rdebug-fns.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/.svn/props/rdebug-fns.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/.svn/props/rdebug-frames.el.svn-work b/emacs/.svn/props/rdebug-frames.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-frames.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-gud.el.svn-work b/emacs/.svn/props/rdebug-gud.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-gud.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-help.el.svn-work b/emacs/.svn/props/rdebug-help.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-help.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-info.el.svn-work b/emacs/.svn/props/rdebug-info.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/.svn/props/rdebug-info.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/.svn/props/rdebug-layouts.el.svn-work b/emacs/.svn/props/rdebug-layouts.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-layouts.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-locring.el.svn-work b/emacs/.svn/props/rdebug-locring.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-locring.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-output.el.svn-work b/emacs/.svn/props/rdebug-output.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-output.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-regexp.el.svn-work b/emacs/.svn/props/rdebug-regexp.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-regexp.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-secondary.el.svn-work b/emacs/.svn/props/rdebug-secondary.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-secondary.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-shortkey.el.svn-work b/emacs/.svn/props/rdebug-shortkey.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-shortkey.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-source.el.svn-work b/emacs/.svn/props/rdebug-source.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-source.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-track.el.svn-work b/emacs/.svn/props/rdebug-track.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-track.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-varbuf.el.svn-work b/emacs/.svn/props/rdebug-varbuf.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-varbuf.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-vars.el.svn-work b/emacs/.svn/props/rdebug-vars.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-vars.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug-watch.el.svn-work b/emacs/.svn/props/rdebug-watch.el.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/emacs/.svn/props/rdebug-watch.el.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/emacs/.svn/props/rdebug.el.svn-work b/emacs/.svn/props/rdebug.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/.svn/props/rdebug.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/.svn/text-base/Makefile.am.svn-base b/emacs/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 0000000..2bbc81e --- /dev/null +++ b/emacs/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,130 @@ +# Copyright (C) 2007, 2008 Rocky Bernstein rocky@gnu.org +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with Bash; see the file COPYING. If not, write to the Free Software +# Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. +#$Id: Makefile.am,v 1.10 2007/04/13 00:59:33 rockyb Exp $ + +lisp_files = rdebug.el \ + rdebug-annotate.el \ + rdebug-breaks.el \ + rdebug-cmd.el \ + rdebug-core.el \ + rdebug-dbg.el \ + rdebug-error.el \ + rdebug-fns.el \ + rdebug-frames.el \ + rdebug-gud.el \ + rdebug-help.el \ + rdebug-info.el \ + rdebug-layouts.el \ + rdebug-locring.el \ + rdebug-output.el \ + rdebug-regexp.el \ + rdebug-secondary.el\ + rdebug-shortkey.el \ + rdebug-source.el \ + rdebug-track.el \ + rdebug-varbuf.el \ + rdebug-vars.el \ + rdebug-watch.el +check_DATA = test/elk-test.el \ + test/test-annotate.el \ + test/test-cmd.el \ + test/test-core.el \ + test/test-fns.el \ + test/test-gud.el \ + test/test-indent.el \ + test/test-regexp.el \ + test/test-shortkey.el + +EXTRA_DIST = $(lisp_files) $(check_DATA) +ELCFILES = rdebug.elc \ + rdebug-annotate.elc \ + rdebug-breaks.elc \ + rdebug-cmd.elc \ + rdebug-core.elc \ + rdebug-dbg.elc \ + rdebug-error.elc \ + rdebug-fns.elc \ + rdebug-gud.elc \ + rdebug-frames.elc \ + rdebug-help.elc \ + rdebug-info.elc \ + rdebug-layouts.elc \ + rdebug-locring.elc \ + rdebug-output.elc \ + rdebug-regexp.elc \ + rdebug-secondary.elc \ + rdebug-shortkey.elc \ + rdebug-source.elc \ + rdebug-track.elc \ + rdebug-varbuf.elc \ + rdebug-vars.elc \ + rdebug-watch.elc +if INSTALL_EMACS_LISP +lisp_LISP = $(lisp_files) +CHECK_FILES = \ + check-annotate \ + check-cmd \ + check-core \ + check-fns \ + check-frames \ + check-gud \ + check-indent \ + check-regexp \ + check-shortkey + +check: $(CHECK_FILES) + +check-annotate: rdebug-annotate.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-annotate.el ) + +check-cmd: rdebug-gud.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-cmd.el ) + +check-core: rdebug-core.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-core.el ) + +check-fns: rdebug-fns.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-fns.el ) + +check-frames: rdebug-frames.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-frames.el ) + +check-gud: rdebug-gud.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-gud.el ) + +check-indent: $(lisp_files) + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-indent.el ) + +check-regexp: rdebug-regexp.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-regexp.el ) + +check-shortkey: rdebug-shortkey.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-shortkey.el ) +endif + +PHONY = $(CHECK_FILES) + +test: check + diff --git a/emacs/.svn/text-base/rdebug-annotate.el.svn-base b/emacs/.svn/text-base/rdebug-annotate.el.svn-base new file mode 100644 index 0000000..eba89b0 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-annotate.el.svn-base @@ -0,0 +1,385 @@ +;;; rdebug-annotate.el --- Ruby debugger output filtering - which +;;; includes annotation handling. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file contains code dealing with filter of debugger output a large +;; part of which may contain annotations. + +;;; Code: + +(require 'gud) +(require 'gdb-ui) +(require 'rdebug-dbg) +(require 'rdebug-error) +(require 'rdebug-fns) +(require 'rdebug-info) +(require 'rdebug-layouts) +(require 'rdebug-locring) +(require 'rdebug-regexp) +(require 'rdebug-shortkey) +(require 'rdebug-source) +(require 'rdebug-vars) + +(defvar rdebug-non-annotated-text-kind nil + "Represent what non-annotated text is. + +This can be: + * nil -- plain shell output + * :output -- output from the command being debugged + * :info -- text for the \"info\" secondary window. + * :message -- message the text to the echo area. + * :cmd -- a command + result, which might go into the \"info\" window. + +See the function `rdebug-cmd-process' for details on :cmd.") + +(defvar rdebug-annotation-setup-map + (progn + (define-hash-table-test 'str-hash 'string= 'sxhash) + (let ((map (make-hash-table :test 'str-hash))) + (puthash "breakpoints" 'rdebug-setup-breakpoints-buffer map) + ;;(puthash "error" 'rdebug-setup-error-buffer map) + (puthash "frame" 'rdebug-setup-frame-buffer map) + (puthash "variables" 'rdebug-setup-variables-buffer map) + (puthash "watch" 'rdebug-setup-watch-buffer map) + (puthash "output" 'rdebug-setup-output-buffer map) + (puthash "info" 'rdebug-setup-info-buffer map) + (puthash "help" 'rdebug-setup-secondary-window-help-buffer map) + map))) + +(defun rdebug-temp-show (text) + "Arrange to show string as in sort of temporary way. Perhaps like a tooltip" + (tooltip-show text)) + +(defun rdebug-marker-filter-next-item (string) + "The next item for the rdebug marker filter to process. + +Return (item . rest) or nil." + (rdebug-debug-message "ACC: %S" string) + (cond + ;; Empty line, we're done. + ((equal (length string) 0) + nil) + ;; A single ^Z, this could become a new annotation, so lets stop here. + ((string= string "\032") + nil) + ;; A half-baked annotation, lets stop here. + ((and (string-match "^\032\032" string) + (not (string-match "\n" string))) + nil) + (t + (let ((split-point + (cond ((string-match "\032\032" string) + (let ((beg (match-beginning 0))) + (if (equal beg 0) + (if (string-match "^\032\032" string 2) + (match-beginning 0) + (length string)) + beg))) + ((eq (elt string (- (length string) 1)) ?\32) + -1) + (t + (length string))))) + (cons (substring string 0 split-point) (substring string split-point)))))) + +;; There's no guarantee that Emacs will hand the filter the entire +;; marker at once; it could be broken up across several strings. We +;; might even receive a big chunk with several markers in it. If we +;; receive a chunk of text which looks like it might contain the +;; beginning of a marker, we save it here between calls to the +;; filter. +(defun gud-rdebug-marker-filter (string) + "Filter function for process output of the rdebug Ruby debugger." + (rdebug-debug-enter "gud-rdebug-marker-filter:" + (rdebug-debug-message "GOT: %S" string) + (if rdebug-non-annotated-text-kind + (rdebug-debug-message " Text is %S" rdebug-non-annotated-text-kind)) + (setq gud-marker-acc (concat gud-marker-acc string)) + (rdebug-debug-message "TOT: %S" gud-marker-acc) + (let ((shell-output "") ; Output to debugger shell window. + (done nil) + item) + ;; The following loop peels of one "item" at a time. An item is + ;; a un-annotated section or an annotation. (This is taken care + ;; of by the `rdebug-marker-filter-next-item' function.) + ;; + ;; An Annotation can be a one-liner (where anything following + ;; the annotation is treated as un-annotated text) or a full + ;; annotation (which stretches to the next annotation). + ;; + ;; The concept of one-liners (no phun intended) is to allow + ;; continuous output, a "starting" annotation simply sets up the + ;; environment for sending lines to the output window, any text + ;; following it right now, or in later chunks of data, is + ;; redirected to the output window. + (while (and (not done) + (let ((pair (rdebug-marker-filter-next-item gud-marker-acc))) + (rdebug-debug-message "Next item: %S" pair) + (and pair + (progn + (setq item (car pair)) + (setq gud-marker-acc (cdr pair)) + t)))) + ;; Note: Regexp:s are greedy, i.e. the char parts wins over + ;; the .* part. + (if (not (string-match "^\032\032\\([-a-z]*\\).*\n" item)) + ;; Non-annotated text (or the content of one-liners) goes + ;; straight into the debugger shell window, or to the + ;; output window. + (cond ((and (eq rdebug-non-annotated-text-kind :output) + rdebug-use-separate-io-buffer) + (rdebug-process-annotation "starting" item)) + ((eq rdebug-non-annotated-text-kind :info) + (rdebug-process-annotation "info" item)) + (t + (if (eq rdebug-non-annotated-text-kind :cmd) + (rdebug-cmd-process item)) + (setq shell-output (concat shell-output item)))) + ;; Handle annotation. + (let* ((line-end (match-end 0)) + (name (match-string 1 item)) + ;; "prompt" is needed to handle "quit" in the shell correctly. + (one-liner + (member name + '("" "exited" "source" "prompt" "starting"))) + (next-annotation (string-match "\032\032" + gud-marker-acc))) + ;; For one-liners, shuffle some text back to the accumulator. + (when one-liner + (setq gud-marker-acc (concat (substring item line-end) + gud-marker-acc)) + (setq item (substring item 0 line-end))) + (if (or next-annotation + one-liner) + ;; ok, annotation complete, process it and remove it + (let* ((contents (substring item line-end)) + (old-kind rdebug-non-annotated-text-kind)) + (rdebug-debug-message "Name: %S Content: %S Kind: %S" + name contents + rdebug-non-annotated-text-kind) + + ;; This is a global state flag, this allows us to + ;; redirect any further text to the output buffer. + (set + (make-local-variable 'rdebug-non-annotated-text-kind) + (cond ((string= name "starting") + :output) + ((string= name "prompt") + (rdebug-cmd-clear) + :cmd) + ((string= name "exited") + ;; Create a fake command whose output we + ;; handle in the cmd system. (We might not + ;; receive all of the message at once, we we + ;; need some kind of accumukator, which the + ;; cmd system provides.) + (setq rdebug-inferior-status "exited") + (rdebug-cmd-clear) + (setq rdebug-call-queue + (cons '("***exited***" :message) + rdebug-call-queue)) + :cmd) + (t nil))) + + (when (and (eq old-kind :cmd) + (not (eq rdebug-non-annotated-text-kind :cmd))) + (rdebug-debug-message + "New kind: %S" rdebug-non-annotated-text-kind) + (rdebug-cmd-done)) + + ;; Process the annotation. + (cond ((string= name "starting") + (setq rdebug-inferior-status "running")) + ((string= name "stopped") + (setq rdebug-inferior-status "stopped")) + ((string= name "exited") + (setq rdebug-inferior-status "exited")) + ((string= name "pre-prompt") + ;; Strip of the trailing \n (this is probably + ;; a bug in processor.rb). + (if (string= (substring contents -1) "\n") + (setq contents (substring contents 0 -1))) + (if (string-match "post-mortem" contents) + (setq rdebug-inferior-status "crashed")) + (setq shell-output (concat shell-output contents))) + ((string= name "source") + (if (string-match gud-rdebug-marker-regexp item) + ;; Extract the frame position from the marker. + (setq gud-last-frame + (cons (match-string 1 item) + (string-to-number + (match-string 2 item)))))) + (t (rdebug-process-annotation name contents)))) + ;; This is not a one-liner, and we haven't seen the next + ;; annotation, so we have to treat this as a partial + ;; annotation. Save it and hope that the we can process + ;; it the next time we're called. + (setq gud-marker-acc (concat item gud-marker-acc)) + (setq done t))))) + + (when gud-last-frame + ;; Display the source file where we want it, gud will only pick + ;; an arbitrary window. + (rdebug-pick-source-window) + (rdebug-set-frame-arrow (gud-find-file (car gud-last-frame))) + (if (equal 0 rdebug-frames-current-frame-number) + (rdebug-locring-add gud-last-frame + rdebug-source-location-ring))) + (rdebug-short-key-mode-maybe-activate) + + (unless (string= shell-output "") + (rdebug-debug-message "Output: %S" shell-output)) + (rdebug-debug-message "REM: %S" gud-marker-acc) + + shell-output))) + +(defun rdebug-process-annotation (name contents) + "Called after `gud-rdebug-marker-filter' found a complete +`name' annotation with string `contents'. Send it to the right +place for processing." + (rdebug-debug-enter (format "rdebug-process-annotation %s" name) + ;; Ruby-debug uses the name "starting" for process output (just like + ;; GDB). However, it's better to present the buffer as "output" to + ;; the user. Ditto for "display" and "watch". + (cond ((string= name "starting") + (setq name "output")) + ((string= name "display") + (setq name "watch")) + ((string= name "stack") + (setq name "frame")) + ((string= name "error-begin") + (setq name "error"))) + ;; New "info" + (if (string= name "exited") + (setq name "info")) + (if (string= name "error") + (rdebug-errmsg contents)) + (let ((setup-func (gethash name rdebug-annotation-setup-map))) + (when setup-func + (let ((buf (rdebug-get-buffer name gud-target-name)) + ;; Buffer local, doesn't survive the buffer change. + (comint-buffer gud-comint-buffer)) + (with-current-buffer buf + (setq buffer-read-only t) + (let ((inhibit-read-only t)) + (set (make-local-variable 'rdebug-current-line-number) + (line-number-at-pos)) + (set (make-local-variable 'gud-last-frame) gud-last-frame) + (if rdebug-accumulative-buffer + (goto-char (point-max)) + (erase-buffer)) + (insert contents) + (funcall setup-func buf comint-buffer)))))) + (cond ((and (string= name "info") + (not (string= contents ""))) + (save-selected-window + (rdebug-display-info-buffer)))))) + + +;; ------------------------------------------------------------ +;; Mode line displayer. +;; + +;; The variable rdebug-mode-line-process uses this to generate the +;; actual string to display. +(defun rdebug-display-inferior-status () + "Return a (propertized) string, or nil, to be displayed in the mode line." + (if (and gud-comint-buffer + (buffer-name gud-comint-buffer) + (get-buffer-process gud-comint-buffer) + rdebug-inferior-status) + (let ((s rdebug-inferior-status)) + (cond ((string= rdebug-inferior-status "running") + (setq s (propertize s 'face font-lock-type-face))) + (t + (setq s (propertize s 'face font-lock-warning-face)))) + (concat ":" s)) + ;; No process, don't display anything. + nil)) + +;; ------------------------------------------------------------ +;; Command output parser. +;; + +(defvar rdebug-cmd-acc "" + "The accumulated output of the current command. + +Note, on some systems the external process echoes the command, +which is included in the output.") + +;; Called when a new command starts. +(defun rdebug-cmd-clear () + "Called when the Rdebug filter find the start of a new commands." + (rdebug-debug-enter "rdebug-cmd-clear" + (setq rdebug-cmd-acc ""))) + +;; Called with command output, this can be called any number of times. +(defun rdebug-cmd-process (s) + "Called when the Rdebug filter find the command output. +This may be called any number of times." + (rdebug-debug-enter (format "rdebug-cmd-process %S" s) + (setq rdebug-cmd-acc (concat rdebug-cmd-acc s)))) + +;; Called when command has finished. +(defun rdebug-cmd-done () + "Called when the Rdebug filter find the end of a commands." + (rdebug-debug-enter "rdebug-cmd-done" + ;; car-safe is used since rdebug-call-queue can be empty. + (let ((entry (car-safe rdebug-call-queue)) + (text rdebug-cmd-acc)) + (when entry + (rdebug-debug-message "Entry: %S Acc:%S" rdebug-call-queue rdebug-cmd-acc) + (setq rdebug-call-queue (cdr rdebug-call-queue)) + (let ((saved-cmd (car entry)) + (options (cdr entry))) + ;; In cast the external process echoed the actual command, + ;; remove it. + (when (and (>= (length text) + (length saved-cmd)) + (string= saved-cmd (substring text 0 (length saved-cmd)))) + (setq text (substring text (+ 1 (length saved-cmd))))) + (rdebug-debug-message "Text: %S" text) + ;; Optionally display the result. + (if (memq :tooltip options) + (rdebug-temp-show text)) + (if (memq :info options) + (rdebug-process-annotation "info" text)) + (when (memq :message options) + ;; Remove trailing newlines (chomp). + (while (and (> (length text) 0) + (eq (elt text (- (length text) 1)) ?\n)) + (setq text (substring text 0 -1))) + (message text))))))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-annotate) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-annotate.el ends here diff --git a/emacs/.svn/text-base/rdebug-breaks.el.svn-base b/emacs/.svn/text-base/rdebug-breaks.el.svn-base new file mode 100644 index 0000000..8045aee --- /dev/null +++ b/emacs/.svn/text-base/rdebug-breaks.el.svn-base @@ -0,0 +1,407 @@ +;;; rdebug-breaks.el --- This file contains code dealing with the Ruby +;;; debugger's breakpoints and the breakpoint secondary buffer. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file contains code dealing with the breakpoints and the +;; breakpoints secondary buffer. + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-gud) +(require 'rdebug-regexp) +(require 'rdebug-secondary) +(require 'rdebug-source) +(require 'rdebug-vars) + +(defun rdebug-display-breakpoints-buffer () + "Display the rdebug breakpoints buffer." + (interactive) + (rdebug-display-secondary-buffer "breakpoints")) + +(defvar rdebug-breakpoint-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [double-mouse-1] 'rdebug-goto-breakpoint-mouse) + (define-key map [mouse-2] 'rdebug-goto-breakpoint-mouse) + (define-key map [mouse-3] 'rdebug-goto-breakpoint-mouse) + (define-key map "t" 'rdebug-toggle-breakpoint) + (define-key map "i" 'rdebug-add-breakpoint-condition) + (define-key map [insert] 'rdebug-add-breakpoint-condition) + (rdebug-populate-digit-keys map) + (define-key map [(control m)] 'rdebug-goto-breakpoint) + (define-key map [?d] 'rdebug-delete-breakpoint) + (rdebug-populate-secondary-buffer-map map) + + ;; -------------------- + ;; The "Breakpoints window" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key-after map [menu-bar debugger breakpoints] + (cons "Breakpoints window" submenu) + 'placeholder)) + + (define-key map [menu-bar debugger breakpoints toggle] + '(menu-item "Toggle breakpoint" rdebug-toggle-breakpoint)) + + (define-key map [menu-bar debugger breakpoints goto] + '(menu-item "Goto breakpoint" rdebug-goto-breakpoint)) + + (define-key map [menu-bar debugger breakpoints delete] + '(menu-item "Delete breakpoint" rdebug-delete-breakpoint)) + + map) + "Keymap to navigate/set/enable rdebug breakpoints.") + +;; Here the "anchored match" method is used, see `font-lock-keywords' +;; for details. +(defvar rdebug-breakpoint-font-lock-keywords + '(("\\([0-9]+\\) +\\(\\(n\\)\\|\\(y\\)\\) +at " + (1 font-lock-constant-face) + (3 font-lock-type-face nil t) ; t = ok if not present + (4 font-lock-warning-face nil t) ; ditto. + ;; File name and line + ("\\(.*\\):\\([0-9]+\\)$" + nil ; Preform (not used) + nil ; Postfrom (not used) + (1 font-lock-warning-face) + (2 font-lock-constant-face)) + ;; Class:function + ("\\(.*\\):\\([a-zA-Z_].+\\)$" + nil ; Preform (not used) + nil ; Postfrom (not used) + (1 font-lock-type-face) + (2 font-lock-function-name-face)))) + "Rules for coloring the rdebug breakpoints buffer.") + +(defun rdebug-breakpoint-mode () + "Major mode for displaying breakpoints in the `rdebug' Ruby debugger. + +\\{rdebug-breakpoint-mode-map}" + (kill-all-local-variables) + (setq major-mode 'rdebug-breakpoint-mode) + (setq mode-name "RDEBUG Breakpoints") + (use-local-map rdebug-breakpoint-mode-map) + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (set (make-local-variable 'font-lock-defaults) + '(rdebug-breakpoint-font-lock-keywords)) + (run-mode-hooks 'rdebug-breakpoint-mode-hook)) + + +(defun rdebug-setup-breakpoints-buffer (buf comint-buffer) + "Detect breakpoint lines and set up keymap and mouse navigation. +Argument BUF is the buffer to set up. +Argument COMINT-BUFFER is the assocaited gud process buffer." + (rdebug-debug-enter "rdebug-setup-breakpoints-buffer" + (with-current-buffer buf + (let ((inhibit-read-only t) + (old-line-number (buffer-local-value 'rdebug-current-line-number + buf))) + (rdebug-breakpoint-mode) + (goto-char (point-min)) + (while (not (eobp)) + (let ((b (line-beginning-position)) (e (line-end-position))) + (when (string-match rdebug-breakpoint-regexp + (buffer-substring b e)) + (add-text-properties b e + (list 'mouse-face 'highlight + 'keymap rdebug-breakpoint-mode-map))) + (forward-line))) + (goto-line old-line-number))) + (rdebug-breakpoint-parse-and-update-cache) + (rdebug-breakpoint-update-icons (rdebug-breakpoint-all)))) + + +(defvar rdebug-breakpoint-cache '() + "The cached return value of `rdebug-breakpoint-all'. + +Buffer-local to the debugger shell window.") + + +;; Implementation note: If Emacs could talk directly to the Ruby +;; debugger, this would be roughly "Debugger.breakpoints". Since we +;; currently can't do that we parse the content of the breakpoints +;; window. +;; +;; Note: The :function kind is not yet implemented. +(defun rdebug-breakpoint-parse-and-update-cache () + "Build up the return value of `rdebug-breakpoint-all'." + (save-excursion + (goto-char (point-min)) + (let ((res '())) + (while (not (eobp)) + (when (looking-at rdebug-breakpoint-regexp) + (push (list :file + ;; Break point number + (string-to-number (match-string 1)) + ;; Enabled + (string= (match-string 2) "y") + ;; File name + (file-truename + (match-string-no-properties 3)) + ;; Line number + (string-to-number (match-string 4))) + res)) + (forward-line 1)) + ;; The result goes into a buffer-local variable in the debugger + ;; shell. (This ensures that this would work in a multi-session + ;; environment.) + (if gud-comint-buffer + (with-current-buffer gud-comint-buffer + (set (make-local-variable 'rdebug-breakpoint-cache) + (nreverse res))))))) + + +(defun rdebug-breakpoint-all () + "Return a list of all breakpoints. + +Each entry in the list is on the form: + + (:file number enabled file line) + +or + + (:function number enabled class function)" + (and gud-comint-buffer + (buffer-local-value 'rdebug-breakpoint-cache gud-comint-buffer))) + + +(defun rdebug-file-and-line-arg () + "Return the current file and line number as a list." + (save-excursion + (beginning-of-line) + (list (buffer-file-name) (+ 1 (count-lines (point-min) (point)))))) + +(defun rdebug-breakpoint-on-line (file line) + "Return a list of the breakpoints on the file FILE and current source LINE." + (let ((res '())) + (dolist (entry (rdebug-breakpoint-all)) + (if (and (eq (nth 0 entry) :file) + (string= (nth 3 entry) file) + (equal (nth 4 entry) line)) + (push entry res))) + res)) + + +(defun rdebug-toggle-source-breakpoint (file line) + "Toggle break point in FILE on current source LINE." + (interactive (rdebug-file-and-line-arg)) + (cond ((eq major-mode 'rdebug-breakpoint-mode) + (rdebug-delete-breakpoint)) + ((null file) + ;; Do nothing. + ) + (t + (let ((bps (rdebug-breakpoint-on-line file line))) + (if bps + (gud-call (format "delete %s" (nth 1 (car bps)))) + (gud-call (format "break %s:%d" file line))))))) + + +(defun rdebug-toggle-source-breakpoint-enabled (file line) + "Enable or disable a breakpoint in FILE on the current source LINE." + (interactive (rdebug-file-and-line-arg)) + (cond ((eq major-mode 'rdebug-breakpoint-mode) + (rdebug-toggle-breakpoint)) + ((null file) + ;; Do nothing. + ) + (t + (let ((bps (rdebug-breakpoint-on-line file line))) + (if bps + ;; Note: If the line contains more than one simply use the + ;; first one. + (let ((entry (car bps))) + (if (nth 2 entry) + (gud-call (format "disable %s" (nth 1 entry))) + (gud-call (format "enable %s" (nth 1 entry))))) + (gud-call (format "break %s:%d" file line))))))) + + +;; --------------------------------------------------------- +;; Commands of the rdebug breakpoints buffer. +;; + +(defun rdebug-delete-breakpoint (&optional pt) + "Deletes the breakpoint at PT in the breakpoints buffer." + (interactive "d") + (save-excursion + (if pt + (goto-char pt)) + (let ((s (buffer-substring (line-beginning-position) (line-end-position)))) + (when (string-match rdebug-breakpoint-regexp s) + (let ((bpnum (substring s (match-beginning 1) (match-end 1)))) + (gud-call (format "delete %s" bpnum))))))) + +(defun rdebug-goto-breakpoint (pt) + "Displays the location in a source file of the selected breakpoint. +Argument PT indicates the file and line where the breakpoint should be set." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (buffer-substring (line-beginning-position) (line-end-position)))) + (when (string-match rdebug-breakpoint-regexp s) + (rdebug-display-line + (substring s (match-beginning 3) (match-end 3)) + (string-to-number (substring s (match-beginning 4) (match-end 4)))) + )))) + + +(defun rdebug-goto-breakpoint-mouse (event) + "Displays the location in a source file of the selected breakpoint." + (interactive "e") + (with-current-buffer (window-buffer (posn-window (event-end event))) + (rdebug-goto-breakpoint (posn-point (event-end event))))) + + +(defun rdebug-get-breakpoint-number (pt) + "Return the current breakpoint number in the breakpoint secondary window or nil if none found." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (buffer-substring (line-beginning-position) (line-end-position)))) + (if (string-match rdebug-breakpoint-regexp s) + (substring s (match-beginning 1) (match-end 1)) + nil)))) + +(defun rdebug-toggle-breakpoint (&optional pt) + "Toggle the breakpoint at PT in the breakpoints buffer." + (interactive "d") + (save-excursion + (if pt + (goto-char pt)) + (let ((s (buffer-substring (line-beginning-position) (line-end-position)))) + (when (string-match rdebug-breakpoint-regexp s) + (let* ((enabled + (string= (substring s (match-beginning 2) (match-end 2)) "y")) + (cmd (if enabled "disable" "enable")) + (bpnum (substring s (match-beginning 1) (match-end 1)))) + (gud-call (format "%s breakpoint %s" cmd bpnum))))))) + +(defun rdebug-add-breakpoint-condition (pt) + "Add an expression as a condition to the break `rdebug' Ruby debugger." + (interactive "d") + (let ((bpnum (rdebug-get-breakpoint-number pt)) + (expr (read-string "Ruby expression for breakpoint condition: "))) + (if bpnum + (gud-call (format "condition %s %s" bpnum expr)) + (message "Breakpoint number not found")))) + + +;; ----------------------------------------------- +;; Breakpoint icon support. +;; + +;; This is a trivial implementation, it has the following shortcomings: +;; +;; * It assumes that the buffer content doesn't change, if it does it +;; will not be able to remove the icon. +;; +;; * No support for displaying an icon in a newly opened file. +;; +;; * It has no support for more than one session. + +;; Note: This is implemented on top of `gdb-ui'. In the future, it +;; would be better if that code is generalized. + +(require 'gdb-ui) + +;; This is a local variable, should not be placed in rdebug-vars.el. +(defvar rdebug-breakpoint-icons-current-state nil) + +(defun rdebug-breakpoint-remove-icon (entry) + "Remove the the source buffer the fringe breakpoint icon breakpoint ENTRY." + (if (eq (nth 0 entry) :file) + (let ((buf (find-buffer-visiting (nth 3 entry)))) + (if buf + (save-current-buffer + (set-buffer buf) + (save-excursion + (goto-line (nth 4 entry)) + (gdb-remove-breakpoint-icons (point) (point)))))))) + +(defun rdebug-breakpoint-remove-all-icons () + "Remove all breakpoint fringe icons." + (interactive) + (dolist (entry rdebug-breakpoint-icons-current-state) + (rdebug-breakpoint-remove-icon entry)) + (setq rdebug-breakpoint-icons-current-state nil)) + + +(defun rdebug-breakpoint-add-icon (entry) + (if (eq (nth 0 entry) :file) + (let ((buf (find-buffer-visiting (nth 3 entry)))) + (if buf + (save-current-buffer + (set-buffer buf) + (save-excursion + (goto-line (nth 4 entry)) + ;; Workaround for bug in `gdb-ui'. (It checks + ;; `left-fringe-width' but it doesn't interpret the + ;; `nil' value correctly. + (let ((gdb-buffer-fringe-width (car (window-fringes)))) + (gdb-put-breakpoint-icon (nth 2 entry) + (number-to-string (nth 1 entry)))))))))) + +(defun rdebug-breakpoint-list-member (file line list) + (let ((res nil)) + (dolist (entry list) + (if (and (equal file (nth 3 entry)) + (equal line (nth 4 entry))) + (setq res t))) + res)) + +;; bpts has the same representation as returned by `rdebug-breakpoint-all'. +(defun rdebug-breakpoint-update-icons (bpts) + ;; Make sure there are is only one reference for each line. + (let ((state '())) + ;; An enabled breakpoint take precedence. + (dolist (enabled '(t nil)) + (dolist (bpt bpts) + (if (and (eq (nth 0 bpt) :file) + (eq (nth 2 bpt) enabled) + (not (rdebug-breakpoint-list-member + (nth 3 bpt) (nth 4 bpt) state))) + (setq state (cons bpt state))))) + (dolist (entry rdebug-breakpoint-icons-current-state) + (unless (member entry state) + (rdebug-breakpoint-remove-icon entry))) + (dolist (entry state) + (unless (member entry rdebug-breakpoint-icons-current-state) + (rdebug-breakpoint-add-icon entry))) + (setq rdebug-breakpoint-icons-current-state state))) + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-breaks) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +(provide 'rdebug-breaks) + +;;; rdebug-breaks.el ends here diff --git a/emacs/.svn/text-base/rdebug-cmd.el.svn-base b/emacs/.svn/text-base/rdebug-cmd.el.svn-base new file mode 100644 index 0000000..7a6dfc3 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-cmd.el.svn-base @@ -0,0 +1,92 @@ +;;; rdebug-cmd.el --- Ruby debugger command buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing primarily with the command buffer. + +;;; Code: + +(require 'ring) +(require 'rdebug-locring) + +(defun rdebug-command-initialization () + "Initialization of command buffer common to `rdebug' and`rdebug-track-attach'." + + ;; This opens up "Gud" menu, which isn't used since we've got our + ;; own "Debugger" menu. + ;; (set (make-local-variable 'gud-minor-mode) 'rdebug) + + (set (make-local-variable 'rdebug-call-queue) '()) + (set (make-local-variable 'rdebug-original-read-only) buffer-read-only) + (make-local-variable 'rdebug-source-location-ring-size) ; ...to global val. + (set (make-local-variable 'rdebug-source-location-ring) + (make-ring rdebug-source-location-ring-size)) + (make-local-variable 'rdebug-source-location-ring-index) + (rdebug-locring-clear) + + (gud-def gud-args "info args" "a" + "Show arguments of current stack frame.") + (gud-def gud-break "break %d%f:%l""\C-b" + "Set breakpoint at current line.") + (gud-def gud-cont "continue" "\C-r" + "Continue with display.") + (gud-def gud-down "down %p" "<" + "Down N stack frames (numeric arg).") + (gud-def gud-finish "finish" "\C-f" + "Finish executing current function.") + (gud-def gud-source-resync "up 0" "\C-l" + "Show current source window") + (gud-def gud-remove "clear %d%f:%l" "\C-d" + "Remove breakpoint at current line") + (gud-def gud-quit "quit" "Q" + "Quit debugger.") + + (gud-def gud-statement "eval %e" "\C-e" + "Execute Ruby statement at point.") + (gud-def gud-tbreak "tbreak %d%f:%l" "\C-t" + "Set temporary breakpoint at current line.") + (gud-def gud-up "up %p" + ">" "Up N stack frames to a newer frame (numeric arg).") + (gud-def gud-where "where" + "T" "Show stack trace.") + + (local-set-key [M-insert] 'rdebug-internal-short-key-mode) + (local-set-key [M-down] 'rdebug-locring-newer) + (local-set-key [M-up] 'rdebug-locring-older) + (local-set-key [M-S-down] 'rdebug-locring-newest) + (local-set-key [M-S-up] 'rdebug-locring-oldest) + ;; (local-set-key "\C-i" 'gud-gdb-complete-command) + (local-set-key "\C-c\C-n" 'comint-next-prompt) + (local-set-key "\C-c\C-p" 'comint-previous-prompt)) + +;; stopping location motion routines. + +(provide 'rdebug-cmd) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-cmd.el ends here diff --git a/emacs/.svn/text-base/rdebug-core.el.svn-base b/emacs/.svn/text-base/rdebug-core.el.svn-base new file mode 100644 index 0000000..b31086a --- /dev/null +++ b/emacs/.svn/text-base/rdebug-core.el.svn-base @@ -0,0 +1,502 @@ +;;; rdebug-core.el --- Core parts of the Ruby debugger user +;;; interface. It pulls in other parts of the debugger. + +;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file implements the core of the debugger. + +;;; Code: + +;; ------------------------------------------------------------------- +;; Consistency checks. +;; + +(if (< emacs-major-version 22) + (error + "This version of rdebug.el needs at least Emacs 22 or greater - you have version %d" + emacs-major-version)) + + +;; ------------------------------------------------------------------- +;; Dependencies. +;; + +(require 'gud) +(require 'cl) + +(require 'rdebug) +(require 'rdebug-annotate) +(require 'rdebug-dbg) +(require 'rdebug-cmd) +(require 'rdebug-layouts) +(require 'rdebug-source) +(require 'rdebug-regexp) +(require 'rdebug-vars) + +(defun rdebug-get-script-name (args) + "Parse command line ARGS. + +A list containing the script name, and whether the annotate +option was set is returned. + +Initially annotate should be set to nil. Argument ARGS contains +a tokenized list of the command line." + ;; Parse the following: + ;; + ;; [ruby ruby-options] rdebug rdebug-options script-name script-options + (and args + (let ((name nil) + (annotate-p nil)) + ;; Strip of optional "ruby" or "ruby182" etc. + (when (string-match "^ruby[0-9]*$" + (file-name-sans-extension + (file-name-nondirectory (car args)))) + (pop args) + (while (and args + (string-match "^-" (car args))) + (if (member (car args) '("-e" "-r" "-I" "-C" "-F" "-K")) + (pop args)) + (pop args))) + ;; Remove "rdebug" from "rdebug --rdebug-options script + ;; --script-options" + (pop args) + ;; Skip to the first non-option argument. + (while (and args + (not name)) + (let ((arg (pop args))) + (cond + ;; Annotation or emacs option with level number. + ((or (member arg '("--annotate" "-A")) + (equal arg "--emacs")) + (setq annotate-p t) + (pop args)) + ;; Combined annotation and level option. + ((string-match "^--annotate=[0-9]" arg) + (setq annotate-p t)) + ;; Options with arguments. + ((member arg '("-h" "--host" "-p" "--port" + "-I" "--include" "-r" "--require")) + (pop args)) + ((string-match "^-" arg) + nil) + (t + (setq name arg))))) + (and name + (list name annotate-p))))) + +;; ------------------------------------------------------------------- +;; Window configuration state support. +;; + +(defun rdebug-set-window-configuration-state (state &optional dont-restore) + "Change window configuration state. + +Two states are supported, `original' and `debugger'. + +When `dont-restore' is non-nil, the old window layout is not +restored. This is used when a new layout is being drawn, for +example when the debugger starts." + (rdebug-debug-message "Setting state to %s (was %s)" + state rdebug-window-configuration-state) + (when (not (eq state rdebug-window-configuration-state)) + ;; Save the previous state. + (cond ((not (eq rdebug-window-configuration-state 'original)) + (setq rdebug-debugger-window-configuration + (current-window-configuration))) + ((eq rdebug-window-configuration-state 'original) + (setq rdebug-original-window-configuration + (current-window-configuration)))) + (unless dont-restore + ;; Switch to the saved state, + (cond + ((not (eq state 'original)) + (if rdebug-debugger-window-configuration + (set-window-configuration rdebug-debugger-window-configuration))) + ((eq state 'original) + (if rdebug-original-window-configuration + (set-window-configuration rdebug-original-window-configuration))))) + (setq rdebug-window-configuration-state state))) + + +;; have to bind rdebug-file-queue before installing the kill-emacs-hook +(defvar rdebug-file-queue nil + "Queue of Makefile temp files awaiting execution. +Currently-active file is at the head of the list.") + +(defun rdebug-goto-traceback-line (pt) + "Display the location PT in a source file of the Ruby traceback line." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (buffer-substring (line-beginning-position) (line-end-position))) + (gud-comint-buffer (current-buffer))) + (when (string-match rdebug-traceback-line-re s) + (rdebug-display-line + (substring s (match-beginning 1) (match-end 1)) + (string-to-number (substring s (match-beginning 2) (match-end 2)))) + )))) + +(defun rdebug-goto-dollarbang-traceback-line (pt) + "Display the location PT in a source file of the Ruby $! traceback line." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (buffer-substring (line-beginning-position) (line-end-position))) + (gud-comint-buffer (current-buffer))) + (when (string-match rdebug-dollarbang-traceback-line-re s) + (rdebug-display-line + (substring s (match-beginning 1) (match-end 1)) + (string-to-number (substring s (match-beginning 2) (match-end 2)))) + )))) + +;; ------------------------------------------------------------------- +;; Secondary buffers. +;; + +(require 'rdebug-secondary) +(require 'rdebug-breaks) +(require 'rdebug-frames) +(require 'rdebug-help) +(require 'rdebug-output) +(require 'rdebug-varbuf) +(require 'rdebug-watch) + + +;; ------------------------------------------------------------------- +;; Windows. +;; + +(defun rdebug-setup-windows (&optional erase) + "Create the debugger user interface window layout. + +If ERASE is non-nil, the content of the windows are erased +\(this does not apply to accumulative windows). + +This function displays the source file (or, in some cases, a +buffer list) and creates the window layout. The variable +`rdebug-window-layout-function' controls the function that is +used to perform the actual layout. + +This is only used when `rdebug-many-windows' is non-nil." + (rdebug-debug-enter "rdebug-setup-windows" + (rdebug-set-window-configuration-state 'debugger t) + (pop-to-buffer gud-comint-buffer) + (maphash + (lambda (name func) + (if erase + (let ((buf (rdebug-get-existing-buffer name gud-target-name))) + (if buf + (with-current-buffer buf + (let ((inhibit-read-only t)) + (erase-buffer)))))) + (rdebug-process-annotation name "")) + rdebug-annotation-setup-map) + (let ((buf + (cond (gud-last-last-frame + (gud-find-file (car gud-last-last-frame))) + (gud-target-name + (gud-find-file gud-target-name))))) + ;; Put a buffer in window if we can't find a source file. + (unless buf (setq buf (get-buffer-create "*scratch*"))) + (funcall rdebug-window-layout-function buf gud-target-name)))) + + +(defun rdebug-setup-windows-initially () + "Like `rdebug-setup-windows', but erase the content of accumulative windows. +This is called when the debugger starts." + (rdebug-setup-windows t)) + + +(defun rdebug-restore-debugger-window-layout () + "Restore the initial ruby debugger window layout." + (interactive) + (when rdebug-many-windows + (rdebug-setup-windows))) + +(defun rdebug-display-debugger-window-configuration () + "Switch from the \"original\" to the \"debugger\" window layout. + +The rdebug debugger remembers, and can switch between, two window layouts: + * original -- the window layout when the debugger was started. + * debugger -- the window layout of the debugger, plus all changes made + since the debugger started. + +The check-marks in the \"Window Layout\" menu indicates the +active window layout. + +The function `rdebug-display-original-window-configuration' +switch to the \"original\" window configuration. + +The function `rdebug-restore-debugger-window-layout' restores the +window layout to the state it was when the debugger started." + (interactive) + (rdebug-set-window-configuration-state 'debugger) + (message + "Type `M-x rdebug-display-original-window-configuration RET' to restore.")) + + +;;This function is called upon quitting the debugger and +;;`rdebug-many-windows' is not nil. See also +;;`rdebug-display-debugger-window-configuration'." + +(defun rdebug-display-original-window-configuration () + "Switch from the \"debugger\" to the \"original\" window layout. + +The rdebug debugger remembers, and can switch between, two window layouts: + * original -- the window layout when the debugger was started. + * debugger -- the window layout of the debugger, plus all changes made + since the debugger started. + +The check-marks in the \"Window Layout\" menu indicates the +active window layout. + +The function `rdebug-display-debugger-window-configuration' +switch to the \"debugger\" window configuration." + (interactive) + (rdebug-set-window-configuration-state 'original) + (message + "Type `M-x rdebug-display-debugger-window-configuration RET' to restore.")) + + +;; ------------------------------------------------------------------- +;; The `rdebug' command and support functions. +;; + +(defun rdebug-process-sentinel (process event) + "Restore the original window configuration when the debugger process exits." + (rdebug-debug-enter "rdebug-process-sentinel" + (rdebug-debug-message "status=%S event=%S state=%S" + (process-status process) + event + rdebug-window-configuration-state) + (gud-sentinel process event) + ;; This will "flush" the last annotation. Especially "output" + ;; (a.k.a. "starting") annotations don't have an end markers, if + ;; the last command printed something. + (if (string= event "finished\n") + (gud-rdebug-marker-filter "\032\032\n")) + ;; When the debugger process exited, when the comint buffer has no + ;; buffer process (nil). When the debugger processes is replaced + ;; with another process we should not restore the window + ;; configuration. + (when (and (or (eq rdebug-restore-original-window-configuration t) + (and (eq rdebug-restore-original-window-configuration :many) + rdebug-many-windows)) + (or (rdebug-dead-process-p) + (eq process (get-buffer-process gud-comint-buffer))) + (eq rdebug-window-configuration-state 'debugger) + (not (eq (process-status process) 'run))) + (rdebug-internal-short-key-mode-off) + (rdebug-set-window-configuration-state 'original) + (rdebug-reset-keymaps)))) + + +;; Perform initializations common to all debuggers. +;; The first arg is the specified command line, +;; which starts with the program to debug. +;; The other three args specify the values to use +;; for local variables in the debugger buffer. +(defun rdebug-common-init (rdebug-buffer-name rdebug-cmd-buffer target-name + program args + marker-filter + &optional find-file) + "Perform initializations common to all debuggers. + +RDEBUG-BUFFER-NAME is the specified command line, which starts +with the program to debug. PROGRAM, ARGS and MARKER-FILTER +specify the values to use for local variables in the debugger +buffer." + (if rdebug-cmd-buffer + (progn + (pop-to-buffer rdebug-cmd-buffer) + (when (and rdebug-cmd-buffer (get-buffer-process rdebug-cmd-buffer)) + (error "This program is already being debugged")) + (apply 'make-comint rdebug-buffer-name program nil args) + (or (bolp) (newline))) + (pop-to-buffer (setq rdebug-cmd-buffer + (apply 'make-comint rdebug-buffer-name program nil + args)))) + + ;; Since comint clobbered the mode, we don't set it until now. + (gud-mode) + (set (make-local-variable 'gud-target-name) target-name) + (set (make-local-variable 'gud-marker-filter) marker-filter) + (set (make-local-variable 'gud-minor-mode) 'rdebug) + (set (make-local-variable 'gud-last-frame) nil) + (set (make-local-variable 'gud-last-last-frame) nil) + + (let ((buffer-process (get-buffer-process (current-buffer)))) + (if buffer-process + (progn + (set-process-filter buffer-process 'gud-filter) + (set-process-sentinel buffer-process 'gud-sentinel)))) + (gud-set-buffer)) + +;;;###autoload +(defun rdebug (command-line) + "Invoke the rdebug Ruby debugger and start the Emacs user interface. + +String COMMAND-LINE specifies how to run rdebug. + +By default, the \"standard\" user window layout looks like the following: + ++----------------------------------------------------------------------+ +| Toolbar | ++-----------------------------------+----------------------------------+ +| Debugger shell | Variables buffer | ++-----------------------------------+----------------------------------+ +| | | +| Source buffer | Output buffer | +| | | ++-----------------------------------+----------------------------------+ +| Stack Frame buffer | Breakpoints buffer | ++-----------------------------------+----------------------------------+ + +The variable `rdebug-window-layout-function' can be +customized so that another layout is used. In addition to a +number of predefined layouts it's possible to define a function +to perform a custom layout. + +If `rdebug-many-windows' is nil, only a traditional debugger +shell and source window is opened. + +The directory containing the debugged script becomes the initial +working directory and source-file directory for your debugger. + +The custom variable `gud-rdebug-command-name' sets the command +and options used to invoke rdebug." + (interactive + (let ((init (buffer-file-name))) + (setq init (and init + (file-name-nondirectory init))) + (list (gud-query-cmdline 'rdebug init)))) + (rdebug-debug-enter "rdebug" + (rdebug-set-window-configuration-state 'debugger t) + ;; Parse the command line and pick out the script name and whether + ;; --annotate has been set. + (let* ((words (with-no-warnings + (split-string-and-unquote command-line))) + (script-name-annotate-p (rdebug-get-script-name + (gud-rdebug-massage-args "1" words))) + (target-name (file-name-nondirectory (car script-name-annotate-p))) + (annotate-p (cadr script-name-annotate-p)) + (cmd-buffer-name (format "rdebug-cmd-%s" target-name)) + (rdebug-cmd-buffer-name (format "*%s*" cmd-buffer-name)) + (rdebug-cmd-buffer (get-buffer rdebug-cmd-buffer-name)) + (program (car words)) + (args (cdr words)) + (gud-chdir-before-run nil)) + + ;; `gud-rdebug-massage-args' needs whole `command-line'. + ;; command-line is refered through dynamic scope. + (rdebug-common-init cmd-buffer-name rdebug-cmd-buffer target-name + program args + 'gud-rdebug-marker-filter + 'gud-rdebug-find-file) + (setq comint-process-echoes t) + + (setq rdebug-inferior-status "running") + + (rdebug-command-initialization) + + ;; Setup exit callback so that the original frame configuration + ;; can be restored. + (let ((process (get-buffer-process gud-comint-buffer))) + (when process + (unless (equal rdebug-line-width 120) + (gud-call (format "set width %d" rdebug-line-width))) + (set-process-sentinel process + 'rdebug-process-sentinel))) + + + ;; Add the buffer-displaying commands to the Gud buffer, + ;; FIXME: combine with code in rdebug-track.el; make common + ;; command buffer mode map. + (let ((prefix-map (make-sparse-keymap))) + (define-key (current-local-map) gud-key-prefix prefix-map) + (define-key prefix-map "t" 'rdebug-goto-traceback-line) + (define-key prefix-map "!" 'rdebug-goto-dollarbang-traceback-line) + (rdebug-populate-secondary-buffer-map-plain prefix-map)) + + (rdebug-populate-common-keys (current-local-map)) + (rdebug-populate-debugger-menu (current-local-map)) + + (setq comint-prompt-regexp (concat "^" rdebug-input-prompt-regexp)) + (setq paragraph-start comint-prompt-regexp) + + (setcdr (assq 'rdebug-debugger-support-minor-mode minor-mode-map-alist) + rdebug-debugger-support-minor-mode-map-when-active) + (when rdebug-many-windows + (rdebug-setup-windows-initially)) + + (run-hooks 'rdebug-mode-hook)))) + + +(defadvice gud-reset (before rdebug-reset) + "Rdebug cleanup - remove debugger's internal buffers (frame, breakpoints, etc.)." + (rdebug-breakpoint-remove-all-icons) + (dolist (buffer (buffer-list)) + (when (string-match "\\*rdebug-[a-z]+\\*" (buffer-name buffer)) + (let ((w (get-buffer-window buffer))) + (when w + (delete-window w))) + (kill-buffer buffer)))) +(ad-activate 'gud-reset) + +(defun rdebug-reset () + "Rdebug cleanup - remove debugger's internal buffers (frame, breakpoints, etc.)." + (interactive) + (rdebug-breakpoint-remove-all-icons) + (dolist (buffer (buffer-list)) + (when (string-match "\\*rdebug-[a-z]+\\*" (buffer-name buffer)) + (let ((w (get-buffer-window buffer))) + (when w + (delete-window w))) + (kill-buffer buffer)))) + +(defun rdebug-reset-keymaps() + "This unbinds the special debugger keys of the source buffers." + (interactive) + (setcdr (assq 'rdebug-debugger-support-minor-mode minor-mode-map-alist) + rdebug-debugger-support-minor-mode-map-when-deactive)) + + +(defun rdebug-customize () + "Use `customize' to edit the settings of the `rdebug' debugger." + (interactive) + (customize-group 'rdebug)) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-core) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-core.el ends here diff --git a/emacs/.svn/text-base/rdebug-dbg.el.svn-base b/emacs/.svn/text-base/rdebug-dbg.el.svn-base new file mode 100644 index 0000000..1113b1e --- /dev/null +++ b/emacs/.svn/text-base/rdebug-dbg.el.svn-base @@ -0,0 +1,62 @@ +;;; rdebug-dbg.el --- Ruby debugger frames buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains internal debug trace support. + +;;; Code: + +(require 'rdebug-vars) + +(defun rdebug-debug-message (&rest args) + (if rdebug-debug-active + (let ((buf (get-buffer-create "*Xrdebug*"))) + (with-current-buffer buf + (save-excursion + (goto-char (point-max)) + ;; 32 = space. + (insert (make-string (* 4 rdebug-debug-depth) 32)) + (insert (apply #'format args)) + (insert "\n")))))) + + +(defmacro rdebug-debug-enter (str &rest body) + (declare (indent 1) (debug t)) + `(progn + (rdebug-debug-message "--> %s" ,str) + (setq rdebug-debug-depth (+ rdebug-debug-depth 1)) + (unwind-protect + (progn + ,@body) + (setq rdebug-debug-depth (max 0 (- rdebug-debug-depth 1))) + (rdebug-debug-message "<-- %s" ,str)))) + +(provide 'rdebug-dbg) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-dbg.el ends here diff --git a/emacs/.svn/text-base/rdebug-error.el.svn-base b/emacs/.svn/text-base/rdebug-error.el.svn-base new file mode 100644 index 0000000..74b2ef2 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-error.el.svn-base @@ -0,0 +1,79 @@ +;;; rdebug-error.el --- Ruby debugger error buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the error secondary buffer. + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-fns) +(require 'rdebug-secondary) +(require 'rdebug-source) + +(defun rdebug-display-error-buffer () + "Display the rdebug error buffer." + (interactive) + (rdebug-display-secondary-buffer "error")) + +(defvar rdebug-error-mode-map + (let ((map (make-sparse-keymap))) + (rdebug-populate-secondary-buffer-map map) + map) + "Keymap used in the error buffer in the `rdebug' Ruby debugger.") + +(defun rdebug-error-mode () + "Major mode for displaying the script error in the `rdebug' Ruby debugger. + +\\{rdebug-error-mode}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-error-mode) + (setq mode-name "RDEBUG Error") + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (use-local-map rdebug-error-mode-map) + (run-mode-hooks 'rdebug-error-mode-hook)) + +(defun rebug-setup-error-buffer (buf comint-buffer) + (rdebug-debug-enter "rebug-setup-error-buffer" + (with-current-buffer buf + (rdebug-error-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer)))) + +(defun rdebug-errmsg (msg) +;;; (with-current-buffer (rdebug-get-buffer "error" gud-target-name) +;;; (goto-char (point-max)) +;;; (insert msg)) + (message (chomp msg))) + +(provide 'rdebug-error) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-error.el ends here diff --git a/emacs/.svn/text-base/rdebug-fns.el.svn-base b/emacs/.svn/text-base/rdebug-fns.el.svn-base new file mode 100644 index 0000000..ef0c0f1 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-fns.el.svn-base @@ -0,0 +1,111 @@ +;;; rdebug-fns.el --- Ruby debugger miscellaneous functions + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-frames.el 711 2008-02-20 07:09:17Z andersl $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the frames secondary buffer. + +;;; Code: + +(require 'gud) +(require 'rdebug-vars) + +(defun chomp(string &optional multiple) + "Remove trailing \n if it's there" + (if multiple + (progn + (while (and (> (length string) 0) + (eq (elt string (- (length string) 1)) ?\n)) + (setq string (substring string 0 -1))) + string) + (if (> (length string) 0) + (let ((s string)) + (if (string= "\n" (substring s -1)) + (substring s 0 -1) + s)) + ""))) + +(defun rdebug-dead-process-p () + "Return true if the rdebug comint-process is dead or exited." + ;; FIXME? Use a variable in gud-comint-buffer's status? + (or (not gud-comint-buffer) + (null (get-buffer-process gud-comint-buffer)) + (not (member (process-status gud-comint-buffer) '(run open))))) + +(defun rdebug-get-secondary-buffer-name (name) + "Get the rdebug NAME secondary buffer. If none found return nil." + (let ((target-name + (or (and gud-comint-buffer + (buffer-local-value 'gud-target-name + gud-comint-buffer)) + gud-target-name))) + (cond ((and (string= "cmd" name) gud-comint-buffer) + (buffer-name gud-comint-buffer)) + (t (format "*rdebug-%s-%s*" name target-name))))) + +(defun rdebug-set-frame-top-arrow (buf) + "Set the fringe arrow in BUF to indicate the top frame." + (with-current-buffer buf + (setq fringe-indicator-alist + '((overlay-arrow . right-triangle))))) + +(defun rdebug-set-frame-not-top-arrow (buf) + "Set the fringe arrow in BUF to indicate a frame other than the top frame." + (with-current-buffer buf + (setq fringe-indicator-alist + '((overlay-arrow . hollow-right-triangle))))) + +(defun rdebug-set-frame-arrow (buf) + "Set the fringe arrow in buffer BUF." + (if (equal 0 rdebug-frames-current-frame-number) + (rdebug-set-frame-top-arrow buf) + (rdebug-set-frame-not-top-arrow buf))) + +;; From Emacs 23 +(unless (fboundp 'split-string-and-unquote) + (defun split-string-and-unquote (string &optional separator) + "Split the STRING into a list of strings. +It understands Emacs Lisp quoting within STRING, such that + (split-string-and-unquote (combine-and-quote-strings strs)) == strs +The SEPARATOR regexp defaults to \"\\s-+\"." + (let ((sep (or separator "\\s-+")) + (i (string-match "[\"]" string))) + (if (null i) + (split-string string sep t) ; no quoting: easy + (append (unless (eq i 0) (split-string (substring string 0 i) sep t)) + (let ((rfs (read-from-string string i))) + (cons (car rfs) + (with-no-warnings + (split-string-and-unquote (substring string (cdr rfs)) + sep)))))))) + ) + + +(provide 'rdebug-fns) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-fns.el ends here diff --git a/emacs/.svn/text-base/rdebug-frames.el.svn-base b/emacs/.svn/text-base/rdebug-frames.el.svn-base new file mode 100644 index 0000000..28ab10d --- /dev/null +++ b/emacs/.svn/text-base/rdebug-frames.el.svn-base @@ -0,0 +1,230 @@ +;;; rdebug-frames.el --- Ruby debugger frames buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the frames secondary buffer. + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-fns) +(require 'rdebug-regexp) +(require 'rdebug-secondary) +(require 'rdebug-source) + +(defun rdebug-display-frame-buffer () + "Display the rdebug stack-frame buffer." + (interactive) + (rdebug-display-secondary-buffer "frame")) + +(defvar rdebug-frames-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [double-mouse-1] 'rdebug-goto-frame-mouse) + (define-key map [mouse-2] 'rdebug-goto-frame-mouse) + (define-key map [mouse-3] 'rdebug-goto-frame-mouse) + (define-key map [(control m)] 'rdebug-goto-frame) + (define-key map "0" 'rdebug-goto-frame-n) + (define-key map "1" 'rdebug-goto-frame-n) + (define-key map "2" 'rdebug-goto-frame-n) + (define-key map "3" 'rdebug-goto-frame-n) + (define-key map "4" 'rdebug-goto-frame-n) + (define-key map "5" 'rdebug-goto-frame-n) + (define-key map "6" 'rdebug-goto-frame-n) + (define-key map "7" 'rdebug-goto-frame-n) + (define-key map "8" 'rdebug-goto-frame-n) + (define-key map "9" 'rdebug-goto-frame-n) + (rdebug-populate-secondary-buffer-map map) + + ;; -------------------- + ;; The "Stack window" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key-after map [menu-bar debugger stack] + (cons "Stack window" submenu) + 'placeholder)) + + (define-key map [menu-bar debugger stack goto] + '(menu-item "Goto frame" rdebug-goto-frame)) + map) + "Keymap to navigate rdebug stack frames.") + +(defun rdebug-goto-frame (pt) + "Show the rdebug stack frame corresponding at PT in the rdebug stack buffer." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (concat "-->" (buffer-substring (line-beginning-position) + (line-end-position)))) + (s2 (if (= (line-number-at-pos (line-end-position 2)) + (line-number-at-pos (point-max))) + nil + ;;else + (buffer-substring (line-beginning-position 2) + (line-end-position 2))))) + (when (or (string-match rdebug-stack-frame-regexp s) + ;; need to match 1st line last to get the match position right + (and s2 (string-match rdebug-stack-frame-2nd-regexp s2) + (string-match rdebug-stack-frame-1st-regexp s))) + (let ((frame (substring s (match-beginning 2) (match-end 2)))) + (gud-call (concat "frame " frame))))))) + +(defun rdebug-goto-frame-mouse (event) + "Show the rdebug stack frame under the mouse in the rdebug stack buffer." + (interactive "e") + (with-current-buffer (window-buffer (posn-window (event-end event))) + (rdebug-goto-frame (posn-point (event-end event))))) + +;; The following is split in two to facilitate debugging. +(defun rdebug-goto-frame-n-internal (keys) + (if (and (stringp keys) + (= (length keys) 1)) + (progn + (setq rdebug-goto-entry-acc (concat rdebug-goto-entry-acc keys)) + ;; Try to find the longest suffix. + (let ((acc rdebug-goto-entry-acc)) + (while (not (string= acc "")) + (if (not (rdebug-goto-entry-try acc)) + (setq acc (substring acc 1)) + (gud-call (format "frame %s" acc)) + ;; Break loop. + (setq acc ""))))) + (message "`rdebug-goto-frame-n' must be bound to a number key"))) + +(defun rdebug-goto-frame-n () + "Go to the frame number indicated by the accumulated numeric keys just entered. + +This function is usually bound to a numeric key in a 'frame' +secondary buffer. To go to an entry above 9, just keep entering +the number. For example, if you press 1 and then 9, frame 1 is selected +\(if it exists) and then frame 19 (if that exists). Entering any +non-digit will start entry number from the beginning again." + (interactive) + (if (not (eq last-command 'rdebug-goto-frame-n)) + (setq rdebug-goto-entry-acc "")) + (rdebug-goto-frame-n-internal (this-command-keys))) + +(defun rdebug-frames-match-current-line (limit) + (and rdebug-frames-current-frame-number + (re-search-forward + (concat "^ *#" + (number-to-string rdebug-frames-current-frame-number) + ;; At least one space (so that we don't match #1 when looking for #10). + " +" + ;; The entire line. + ".*" + "\n" + ;; And the next, if this entry was split into two. + "\\( *[^# ].*$\\)?") limit t))) + +(defvar rdebug-frames-current-frame-face 'highlight) + +;; Example of frame buffer content: +;; +;; #0 Integer.under_cover at line test.rb:13 +;; #1 ClassA::Nested::DeepDown.under_cover(p#ClassA::Nested::DeepD...) +;; at line test.rb:12 +;; #2 Object.sune(s#String, i#Fixnum) at line test.rb:24 +;; #3 at line test.rb:27 + +(defvar rdebug-frames-font-lock-keywords + '( + ;; Parameters and first type entry. + ("\\<\\([a-zA-Z_][a-zA-Z0-9_]*\\)#\\([a-zA-Z_][a-zA-Z0-9_]*\\)\\>" + (1 font-lock-variable-name-face) + (2 font-lock-type-face)) + ;; "::Type", which occurs in class name of function and in parameter list. + ("::\\([a-zA-Z_][a-zA-Z0-9_]*\\)" + (1 font-lock-type-face)) + ;; The frame number and first type name, if present. + ("^ *#\\([0-9]+\\) *\\(\\([a-zA-Z_][a-zA-Z0-9_]*\\)[.:]\\)?" + (1 font-lock-constant-face) + (3 font-lock-type-face nil t)) ; t means optional. + ;; File name and line number. + ("at line \\(.*\\):\\([0-9]+\\)$" + (1 font-lock-warning-face) + (2 font-lock-constant-face)) + ;; Function name. + ("\\<\\([a-zA-Z_][a-zA-Z0-9_]*\\)\\.\\([a-zA-Z_][a-zA-Z0-9_]*\\)" + (1 font-lock-type-face) + (2 font-lock-function-name-face)) + (rdebug-frames-match-current-line + (0 rdebug-frames-current-frame-face append))) + "Font-lock rules for the stack frame window in `rdebug'.") + +(defun rdebug-frames-mode () + "Major mode for displaying the stack trace in the `rdebug' Ruby debugger. +\\{rdebug-frames-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-frames-mode) + (setq mode-name "RDEBUG Stack Frames") + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (use-local-map rdebug-frames-mode-map) + (set (make-local-variable 'font-lock-defaults) + '(rdebug-frames-font-lock-keywords)) + (run-mode-hooks 'rdebug-frames-mode-hook)) + +;; Note: This function can't restore the original point alone, since +;; the point is already at the end of the buffer when this is called. +(defun rdebug-setup-frame-buffer (buf comint-buffer) + "Find the current frame and display the corresponding source line. + +Also, cleans the buffer somewhat and sets up help for the font-lock rules." + (rdebug-debug-enter "rdebug-setup-stack-buffer" + (with-current-buffer buf + (let ((inhibit-read-only t) + (current-frame-number 0)) + (rdebug-frames-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer) + (goto-char (point-min)) + (when (re-search-forward "-->" nil t) + (beginning-of-line) + (setq overlay-arrow-position (make-marker)) + (set-marker overlay-arrow-position (point)) + (when (looking-at rdebug-stack-frame-1st-regexp) + (setq current-frame-number + (string-to-number + (match-string rdebug-stack-frame-number-group))) + (set (make-local-variable 'rdebug-frames-current-frame-number) + current-frame-number) + (with-current-buffer comint-buffer + (setq rdebug-frames-current-frame-number current-frame-number)) + (when gud-last-frame + (rdebug-set-frame-arrow (gud-find-file (car gud-last-frame)))) + (rdebug-set-frame-arrow buf))) + ;; Remove initial ' ' or '-->'. + (save-excursion + (goto-char (point-max)) + (beginning-of-line) + (if (> (point) 4) + (delete-rectangle 4 (point)))))))) + +(provide 'rdebug-frames) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-frames.el ends here diff --git a/emacs/.svn/text-base/rdebug-gud.el.svn-base b/emacs/.svn/text-base/rdebug-gud.el.svn-base new file mode 100644 index 0000000..ab65a41 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-gud.el.svn-base @@ -0,0 +1,242 @@ +;;; rdebug-gud.el --- rdebug interface to gud. + +;; Copyright (C) 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains rdebug Emacs routines which interface with gud. + +;;; Code: + +;; ------------------------------------------------------------------- +;; Dependencies. +;; + +(require 'gud) +(require 'rdebug-error) +(require 'rdebug-fns) +(require 'rdebug-regexp) +(require 'rdebug-vars) + + +(defun gud-rdebug-massage-args (file args) + "Change FILE and list ARGS before running the debugger. + +gud requires this routine to be defined." + args) + + +(defun gud-rdebug-find-file (file) + "`rdebug' and `gud' call this with FILE when they encounter a Ruby program file." + + (find-file-noselect file 'nowarn)) + +(defun rdebug-display-line (file line &optional move-arrow) + "Arrange for marker to appear in at FILE and LINE. +The line marker might appear in the Emacs fringe or as an overlay arroe. +Optional argument MOVE-ARROW indicates whether to move any previous indicator." + (if file + (let ((oldpos (and gud-overlay-arrow-position + (marker-position gud-overlay-arrow-position))) + (oldbuf (and gud-overlay-arrow-position + (marker-buffer gud-overlay-arrow-position)))) + (gud-display-line file line) + (unless move-arrow + (when gud-overlay-arrow-position + (set-marker gud-overlay-arrow-position oldpos oldbuf)))))) + +(defun rdebug-stepping (step-or-next &optional arg) + (or arg (setq arg 1)) + ;;(if (not (member '('rdebug-next 'rdebug-step 'digit-argument) last-command)) + ;; (setq rdebug-stepping-prefix "")) + (unless (member rdebug-stepping-prefix '("" "+" "-")) + (setq rdebug-stepping-prefix "")) + (rdebug-call (format "%s%s %d" step-or-next rdebug-stepping-prefix arg))) + + + +;; ------------------------------------------------------------------- +;; Rdebug commands. +;; + +(defun rdebug-call (cmd) + "Run a debugger command with some error checking." + (if (rdebug-dead-process-p) + (rdebug-errmsg + "Can't find a live debugger process buffer to feed the command to.") + (gud-call cmd))) + +(defun rdebug-call-return (cmd &rest options) + "Register a debugger command whose output should be handled specially. + +OPTIONS is zero or more indicators what should happen with the +output. The following are supported: + * :tooltip -- Show the result in a tool-tip. + * :info -- Show the result in the info secondary buffer." + (if (rdebug-dead-process-p) + (rdebug-errmsg + "Can't find a live debugger process buffer to feed the command to.") + (with-current-buffer gud-comint-buffer + (setq rdebug-call-queue + (append rdebug-call-queue (list (cons cmd options)))) + (gud-call cmd)))) + +(defun rdebug-continue (&optional arg) + "Run a debugger \"continue\" command. + +With a numeric ARG, continue to that line number of the current file." + (interactive "p") + (if arg + (rdebug-call (format "continue %d" arg)) + (rdebug-call (format "continue")))) + + +(defun rdebug-next (&optional arg) + "Run a debugger \"next\" command, respecting `rdebug-stepping-prefix'. + +With a numeric ARG, continue to that line number of the current file." + (interactive "p") + (rdebug-stepping "next" arg)) + +(defvar rdebug-stepping-prefix "" + "The kind of stepping modifier that is desired. + +This variable will have a string value which is either \"\", +\"+\", or \"-\"; this string is be appended to the debugger +stepping commands (\"next\", or \"step\").") + +(defun rdebug-print-cmd (expr &optional cmd) + "Run a debugger print (pl, ps, pp, p) command on `EXPR'; `CMD' is the command to run." + (interactive "s") + (unless cmd (setq cmd "pp")) + (rdebug-call-return (format "%s %s " cmd expr) :tooltip)) + +(defun rdebug-print-list-region (from to) + "Run a debugger \"pl\" command on the marked region." + (interactive "r") + (if (> from to) + (let ((tem to)) + (setq to from from tem))) + (rdebug-print-cmd (buffer-substring from to) "pl")) + +(defun rdebug-print-region (from to) + "Run a debugger \"p\" command on the marked region." + (interactive "r") + (if (> from to) + (let ((tem to)) + (setq to from from tem))) + (rdebug-print-cmd (buffer-substring from to) "p")) + +(defun rdebug-print-sorted-region (from to) + "Run a debugger \"ps\" command on the marked region." + (interactive "r") + (if (> from to) + (let ((tem to)) + (setq to from from tem))) + (rdebug-print-cmd (buffer-substring from to) "ps")) + +(defun rdebug-pretty-print-region (from to) + "Run a debugger \"pp\" command on the marked region." + (interactive "r") + (if (> from to) + (let ((tem to)) + (setq to from from tem))) + (rdebug-print-cmd (buffer-substring from to) "pp")) + + +;; +;; The following two commands should be seen as proof-of-concept +;; functions for the info buffer. +;; + +(defun rdebug-pretty-print-to-buffer (s) + "Pretty print expression to the info buffer." + (interactive "sPretty print: ") + (rdebug-call-return (format "pp %s" s) :info)) + +(defun rdebug-pretty-print-region-to-buffer (from to) + "Pretty print expression in region to the info buffer." + (interactive "r") + (rdebug-call-return (format "pp %s" (buffer-substring from to)) :info)) + + + +(defun rdebug-quit () + "Kill the debugger process associated with the current buffer. + +When `rdebug-many-windows' is active, the original window layout +is restored." + (interactive) + (if (yes-or-no-p "Really quit? ") + (rdebug-call "quit unconditionally"))) + +(defun rdebug-restart () + "Restart the debugged Ruby script. + +An exec restart is used." + (interactive) + (if (yes-or-no-p "Restart? ") + (rdebug-call "restart"))) + +(defun rdebug-set-stepping-prefix () + "Set the granularity of stepping on the subsequent 'next' or 'step' command. +As long as repeated next or step commands are given, they inherit this setting." + (interactive) + (setq rdebug-stepping-prefix (this-command-keys))) + +(defun rdebug-step (&optional arg) + "Run a debugger \"next\" command, respecting `rdebug-stepping-prefix'. + +With a numeric ARG, continue to that line number of the current file." + (interactive "p") + (rdebug-stepping "step" arg)) + +(defun rdebug-newer-frame () + "Run a debugger \"down\" command to an newer frame. + +If we try to go down from frame 0, wrap to the end of the file" + (interactive) + (let* ((buf-name (rdebug-get-secondary-buffer-name "frame")) + (buf (or (get-buffer buf-name) (current-buffer)))) + (with-current-buffer buf + ;; Should we add a mode to disable wrapping? + (if (equal rdebug-frames-current-frame-number 0) + (rdebug-call "frame -1") + (rdebug-call "down 1"))))) + +(defun rdebug-older-frame () + "Run a debugger \"up\" command to an older frame." + (interactive) + (let* ((buf-name (rdebug-get-secondary-buffer-name "frame")) + (buf (or (get-buffer buf-name) (current-buffer)))) + (with-current-buffer buf + ;; Should we add a mode to disable wrapping? + (rdebug-call "up 1")))) + +(provide 'rdebug-gud) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-gud.el ends here diff --git a/emacs/.svn/text-base/rdebug-help.el.svn-base b/emacs/.svn/text-base/rdebug-help.el.svn-base new file mode 100644 index 0000000..6b69374 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-help.el.svn-base @@ -0,0 +1,104 @@ +;;; rdebug-help.el --- Ruby debugger help + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the help buffer. + +;;; Code: + +(defvar rdebug-secondary-window-help-mode-map + (let ((map (make-sparse-keymap))) + (suppress-keymap map) + (rdebug-populate-secondary-buffer-map map) + map) + "Keymap used in the help buffer in the `rdebug' Ruby debugger.") + +(defun rdebug-secondary-window-help-mode () + "Major mode for the secondary buffer help text in the `rdebug' Ruby debugger. + +\\{rdebug-secondary-window-help-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-secondary-window-help-mode) + (setq mode-name "RDEBUG Help") + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (use-local-map rdebug-secondary-window-help-mode-map) + (run-mode-hooks 'rdebug-secondary-window-help-mode-hook)) + +(defun rdebug-display-secondary-window-help-buffer () + "Display the rdebug help buffer." + (interactive) + (rdebug-display-secondary-buffer "help")) + +(defun rdebug-setup-secondary-window-help-buffer (buf comint-buffer) + (rdebug-debug-enter "rdebug-setup-secondary-window-help-buffer" + (with-current-buffer buf + (rdebug-secondary-window-help-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer) + (insert "\ + +This is a rdebug secondary window, you can use it to watch a +number of help buffers. Use capital letters to switch between the +available buffers. Lower case letters (and other key +combinations) are used to issue buffer-specific commands. + +Press `C-h m' for more help, when the individual buffers are visible. + + B - Breakpoints buffer. + C - Command buffer (the debugger shell) + O - Output window + S - go to source frame + T - Stack trace buffer + V - Variables buffer + W - Watch buffer + + SPC - step (into) + + - set for step+ and next+ + - - set for step- and next- + _ - set to remove +/- + c - continue + f - finish (step out) + n - next (step over) + p - print + q - quit + r - run (restart) + R - run (restart) + s - step (into) + + > - go down frame (with numeric argument goes down that many frames) + < - go up one frame (with numeric argument goes down that many frames) + + ? - This help text. +")))) + +(provide 'rdebug-help) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-help.el ends here diff --git a/emacs/.svn/text-base/rdebug-info.el.svn-base b/emacs/.svn/text-base/rdebug-info.el.svn-base new file mode 100644 index 0000000..af09933 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-info.el.svn-base @@ -0,0 +1,83 @@ +;;; rdebug-info.el --- This file contains code dealing with the Ruby +;;; debugger's info secondary buffer. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-breaks.el 670 2008-02-06 18:15:28Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-gud) +(require 'rdebug-regexp) +(require 'rdebug-secondary) +(require 'rdebug-source) +(require 'rdebug-vars) + +(defun rdebug-display-info-buffer () + "Display the rdebug breakpoints buffer." + (interactive) + (rdebug-display-secondary-buffer "info")) + +(defvar rdebug-info-mode-map + (let ((map (make-sparse-keymap))) + (rdebug-populate-secondary-buffer-map map) + map) + "Keymap for the Rdebug info secondary buffer.") + +(defun rdebug-info-mode () + "Major mode for Ruby debugger info buffer. + +\\{rdebug-info-mode-map}" + (kill-all-local-variables) + (setq major-mode 'rdebug-info-mode) + (setq mode-name "RDEBUG Info") + (use-local-map rdebug-info-mode-map) + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (run-mode-hooks 'rdebug-info-mode-hook)) + +(defun rdebug-setup-info-buffer (buf comint-buffer) + "Setup the Rdebug debugger info buffer." + (rdebug-debug-enter "rdebug-setup-info-buffer" + (with-current-buffer buf + (let ((inhibit-read-only t) + (old-line-number (buffer-local-value 'rdebug-current-line-number + buf))) + (rdebug-info-mode) + (goto-line old-line-number))))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-info) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-info.el ends here diff --git a/emacs/.svn/text-base/rdebug-layouts.el.svn-base b/emacs/.svn/text-base/rdebug-layouts.el.svn-base new file mode 100644 index 0000000..0b2d998 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-layouts.el.svn-base @@ -0,0 +1,180 @@ +;;; rdebug-layouts.el --- Ruby debugger window layouts. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This is file contains the window layouts that come with rdebug; the +;; code where can be consulted as a guide for creating other window +;; layouts. + +;; See the manual and the file `rdebug.el' for overall information on +;; the ruby debugger rdebug. + +;;; Code: + +(defun rdebug-get-buffer (name script-name) + "Return a rdebug buffer for displaying NAME when debugging SCRIPT-NAME. +If the buffer doesn't exists it is created." + (get-buffer-create (format "*rdebug-%s-%s*" name script-name))) + + +(defun rdebug-get-existing-buffer (name script-name) + "Return a rdebug buffer for displaying NAME when debugging SCRIPT-NAME. +Return nil if the buffer doesn't exists." + (get-buffer (format "*rdebug-%s-%s*" name script-name))) + + +(defun rdebug-window-layout-conservative (src-buf name) + "A conservative rdebug window layout with three windows. + +This window layout mimics the traditional debugger shell and +source window layout, it only add one secondary window. +Initially, the secondary window displays output of the debugged +process, but any secondary buffer can be displayed, press `?' in +the window for more details. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (split-window-horizontally) + (other-window 1) + (switch-to-buffer src-buf) + (other-window 1) + (when rdebug-use-separate-io-buffer + (split-window nil 20) + (set-window-buffer + (selected-window) (rdebug-get-buffer "output" name))) + (other-window 1)) + +(defun rdebug-window-layout-rocky (src-buf name) + "Rocky's window layout. + +3 windows. The source window is on top 4/5 of height. The +bottom is split between the command windows and a stack window. + +See `rdebug' for more information. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (split-window nil ( / ( * (window-height) 4) 5)) + (set-window-buffer + (selected-window) src-buf) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "frame" name)) + (split-window-horizontally) + (set-window-buffer + (selected-window) (rdebug-get-buffer "cmd" name)) + (goto-char (point-max))) + +(defun rdebug-window-layout-rocky2 (src-buf name) + "This layout is standard window without the output window, see `rdebug'. +for more information. +Argument SRC-BUF is the NAME of the buffer containing the Ruby source program that was initially run." + (delete-other-windows) + (split-window nil ( / ( * (window-height) 3) 4)) + (set-window-buffer + (selected-window) src-buf) + (split-window nil ( / (window-height) 3)) + (split-window-horizontally) + (set-window-buffer + (selected-window) (rdebug-get-buffer "frame" name)) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "variables" name)) + (other-window 1) + (switch-to-buffer src-buf) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "cmd" name)) + (goto-char (point-max))) + +(defun rdebug-window-layout-stack-of-windows (src-buf name) + "A rdebug window layout with several secondary windows to the right. +The debugger shell and the source code window is to the left. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (split-window-horizontally) + (split-window nil 20) + (set-window-buffer + (selected-window) (rdebug-get-buffer "cmd" name)) + (other-window 1) + (switch-to-buffer src-buf) + (other-window 1) + (split-window) + (split-window) + (set-window-buffer + (selected-window) (rdebug-get-buffer "variables" name)) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "frame" name)) + (when rdebug-use-separate-io-buffer + (other-window 1) + (split-window) + (set-window-buffer + (selected-window) (rdebug-get-buffer "output" name))) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "breakpoints" name)) + (other-window 1)) + +;; The default layout +(defun rdebug-window-layout-standard (src-buf name) + "The default rdebug window layout, see `rdebug' for more information. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (split-window nil ( / ( * (window-height) 3) 4)) + (split-window nil ( / (window-height) 3)) + (split-window-horizontally) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "variables" name)) + (other-window 1) + (switch-to-buffer src-buf) + (when rdebug-use-separate-io-buffer + (split-window-horizontally) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "output" name))) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "frame" name)) + (split-window-horizontally) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "breakpoints" name)) + (other-window 1) + (goto-char (point-max))) + + +(defun rdebug-window-layout-no-shell (src-buf name) + "A rdebug window layout without a shell window. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (set-window-buffer + (selected-window) (rdebug-get-buffer "watch" name)) + (rdebug-window-layout-standard src-buf name)) + +(provide 'rdebug-layouts) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-layouts.el ends here diff --git a/emacs/.svn/text-base/rdebug-locring.el.svn-base b/emacs/.svn/text-base/rdebug-locring.el.svn-base new file mode 100644 index 0000000..0a36fc2 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-locring.el.svn-base @@ -0,0 +1,118 @@ +;;; rdebug-locring.el --- Ruby debugger location ring + +;; Copyright (C) 2008, 2009 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file manages a ring of (recently stopped) positions to allow +;; the programmer to move back and forth between them. + +;;; Code: + +(defvar rdebug-source-location-ring nil + "Ring of the last `rdebug-source-location-ring-size' positions we've stopped aft.") + +(defvar rdebug-source-location-ring-index -1 + "Position in `rdebug-source-location-ring' of where we are.") + +(defun rdebug-locring-add (frame location-history-ring) + "Add FRAME to LOCATION-HISTORY-RING if we are on the top frame and have a frame to add." + ;; Switching frames shouldn't save a new ring + ;; position. Also make sure no position is different. + ;; Perhaps duplicates should be controlled by an option. + (unless (and (not (ring-empty-p location-history-ring)) + (equal (ring-ref location-history-ring + (ring-length location-history-ring)) frame)) + (ring-insert-at-beginning location-history-ring frame))) + +(defun rdebug-locring-clear () + "Clear out all source locations in `Go to the source location of the first stopping point." + (interactive) + (setq rdebug-source-location-ring-index -1) + (while (not (ring-empty-p rdebug-source-location-ring)) + (ring-remove rdebug-source-location-ring))) + +(defun rdebug-locring-goto (ring-position) + "Go the source position RING-POSITION in the stopping history." + (interactive "NSource location ring position (0 is oldest): ") + (with-current-buffer gud-comint-buffer + (setq rdebug-source-location-ring-index ring-position) + (let* ((frame (ring-ref rdebug-source-location-ring ring-position)) + (file (car frame)) + (line (cdr frame))) + (when file + (rdebug-display-line file line) + (message (format "%d %s:%d" rdebug-source-location-ring-index + file line)))))) + +(defun rdebug-locring-newer () + "Cycle through source location stopping history to get the next newer (more recently visited) location." + (interactive) + (with-current-buffer gud-comint-buffer + (if (equal (+ 1 rdebug-source-location-ring-index) + (ring-length rdebug-source-location-ring)) + (progn + (message "At newest - Will set to wrap to oldest.") + (setq rdebug-source-location-ring-index -1)) + ;; else + (rdebug-locring-goto + (if (> rdebug-source-location-ring-index + (ring-length rdebug-source-location-ring)) + 0 + ;; else + (ring-plus1 rdebug-source-location-ring-index + (ring-length rdebug-source-location-ring))))))) + +(defun rdebug-locring-newest () + "Go to the source location of the first stopping point." + (interactive) + (rdebug-locring-goto (- (ring-length rdebug-source-location-ring) 1))) + +(defun rdebug-locring-older () + "Cycle through source location stopping history to get the next older (least recently visited) location." + (interactive) + (with-current-buffer gud-comint-buffer + (if (equal rdebug-source-location-ring-index 0) + (progn + (message "At oldest - Will set to wrap to newest.") + (setq rdebug-source-location-ring-index + (+ 1 (ring-length rdebug-source-location-ring)))) + ;; else + (rdebug-locring-goto + (if (or (not rdebug-source-location-ring-index) + (< rdebug-source-location-ring-index 0)) + 0 + ;; else + (ring-minus1 rdebug-source-location-ring-index + (ring-length rdebug-source-location-ring))))))) + +(defun rdebug-locring-oldest () + "Go to the oldest source position location." + (interactive) + (ring-ref rdebug-source-location-ring 0)) + +(provide 'rdebug-locring) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-locring.el ends here diff --git a/emacs/.svn/text-base/rdebug-output.el.svn-base b/emacs/.svn/text-base/rdebug-output.el.svn-base new file mode 100644 index 0000000..07b945e --- /dev/null +++ b/emacs/.svn/text-base/rdebug-output.el.svn-base @@ -0,0 +1,106 @@ +;;; rdebug-output.el --- Ruby debugger output buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the output secondary buffer. + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-secondary) + +(defun rdebug-display-output-buffer () + "Display the rdebug output buffer." + (interactive) + (rdebug-display-secondary-buffer "output")) + +;; FIXME add a macro to toggle read-only and run command. +(defun rdebug-output-add-divider () + (interactive "") + (save-excursion + (goto-char (point-max)) + (setq buffer-read-only nil) + ;; FIXME Cooler would be to pick up stack position in stack line + ;; and prepend a buffer-local marker number + (insert (format "%d: ============================\n" + rdebug-output-marker-number)) + (setq rdebug-output-marker-number (+ rdebug-output-marker-number 1)) + (setq buffer-read-only t))) + +(defun rdebug-output-delete-output () + (interactive) + (setq buffer-read-only nil) + (delete-region (point-min) (point-max)) + (setq buffer-read-only t)) + +(defun rdebug-output-undo () ;FIXME make more global? + (interactive "") + (setq buffer-read-only nil) + (undo) + (setq buffer-read-only t)) + +(defvar rdebug-output-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "d" 'rdebug-output-delete-output) + (define-key map "t" 'rdebug-goto-traceback-line) + (define-key map "!" 'rdebug-goto-dollarbang-traceback-line) + (define-key map "=" 'rdebug-output-add-divider) + (define-key map "\C-_" 'rdebug-output-undo) ; FIXME get from keymap + (define-key map "u" 'rdebug-output-undo) + (suppress-keymap map) + (rdebug-populate-secondary-buffer-map map) + map) + "Keymap used in the output buffer in the `rdebug' Ruby debugger.") + +(defun rdebug-output-mode () + "Major mode for displaying the script output in the `rdebug' Ruby debugger. + +\\{rdebug-output-mode}" + (interactive) + (let ((old-marker-number rdebug-output-marker-number)) + (kill-all-local-variables) + (setq major-mode 'rdebug-output-mode) + (setq mode-name "RDEBUG Output") + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (set (make-local-variable 'rdebug-accumulative-buffer) t) + (use-local-map rdebug-output-mode-map) + (set (make-local-variable 'rdebug-output-marker-number) old-marker-number) + (run-mode-hooks 'rdebug-output-mode-hook))) + +(defun rdebug-setup-output-buffer (buf comint-buffer) + (rdebug-debug-enter "rdebug-setup-output-buffer" + (with-current-buffer buf + (rdebug-output-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer)))) + +(provide 'rdebug-output) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-output.el ends here diff --git a/emacs/.svn/text-base/rdebug-regexp.el.svn-base b/emacs/.svn/text-base/rdebug-regexp.el.svn-base new file mode 100644 index 0000000..62e8a83 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-regexp.el.svn-base @@ -0,0 +1,118 @@ +;;; rdebug-regexp.el --- Ruby debugger regular expressions + +;; Copyright (C) 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; Here we have regular expressions and names for matched patterns +;; of those regular expressions. + +;;; Code: + +;; ------------------------------------------------------------------- +;; Variables defining regular expressions (regexp:s). +;; + +(defconst gud-rdebug-marker-regexp + "\\(?:source \\)?\\(\\(?:[a-zA-Z]:\\)?[^:\n]*\\):\\([0-9]*\\).*\n" + "Regular expression used to find a file location given by rdebug. + +Program-location lines look like this: + source /tmp/gcd.rb:29: gcd + /tmp/gcd.rb:29: gcd + source /tmp/gcd.rb:29 + source C:/tmp/gcd.rb:29 + source \\sources\\capfilterscanner\\capanalyzer.rb:3: ") + +(defconst rdebug-annotation-end-regexp + "\n" + "Regular expression to match the end of an annotation.") + +;; Examples of annotations: +;; ^Z^Z\n +;; ^Z^Zfoo\n +;; ^Z^Zpre-prompt\n +;; ^Z^Zsource foo.rb:10\n + +(defconst rdebug-annotation-start-regexp + "\\(\\([a-z][-a-z]*\\)?\n\\|source \\)" + "Regular expression to match the start of an annotation.") + +(defconst rdebug-breakpoint-regexp + "^\\ +\\([0-9]+\\) \\([yn]\\) +at +\\(.+\\):\\([0-9]+\\)\\( if .*\\)?$" + "Regexp to recognize breakpoint lines in rdebug breakpoint buffers.") + +(defconst rdebug-marker-regexp-file-group 2 + "Group position in `rdebug-position-regexp' that matches the file name.") + +(defconst rdebug-marker-regexp-line-group 3 + "Group position in `rdebug-position-regexp' that matches the line number.") + +(defconst rdebug-position-regexp + "\\(\\)\\([-a-zA-Z0-9_/.]*\\):\\([0-9]+\\)" + "Regular expression for a rdebug position.") + +(defconst rdebug-traceback-line-re + "^[ \t]+from \\([^:]+\\):\\([0-9]+\\)\\( in `.*'\\)?" + "Regular expression that describes a Ruby traceback line.") + +(defconst rdebug-dollarbang-traceback-line-re + "^[ \t]+[[]?\\([^:]+\\):\\([0-9]+\\):in `.*'" + "Regular expression that describes a Ruby traceback line from $! list.") + +(defconst rdebug-stack-frame-1st-regexp + "^\\(-->\\| \\) +#\\([0-9]+\\)\\(.*\\)" + "Regexp to match the first line of a stack frame in rdebug stack buffers.") + +(defconst rdebug-stack-frame-number-group 2 + "The group position in `rdebug-stack-frame-1st-regexp' that matches the frame number.") + +(defconst rdebug-stack-frame-2nd-regexp + "\s+at line +\\([^:]+\\):\\([0-9]+\\)$" + "Regexp to match the second line of a stack frame in rdebug stack buffers.") + +(defconst rdebug-stack-frame-2nd-file-group 1 + "Group position in `rdebug-stack-frame-2nd-regexp' that matches the file name.") + +(defconst rdebug-stack-frame-2nd-line-group 2 + "Group position in `rdebug-stack-frame-2nd-regexp' that matches the line number.") +(defconst rdebug-stack-frame-regexp + (concat rdebug-stack-frame-1st-regexp rdebug-stack-frame-2nd-regexp) + "Regexp to recognize a stack frame line in rdebug stack buffers.") + +(defconst rdebug-stack-frame-file-group 4 + "Group position in `rdebug-stack-frame-regexp' that matches the file name.") + +(defconst rdebug-stack-frame-line-group 5 + "Group position in `rdebug-stack-frame-regexp' that matches the line number.") + +(defconst rdebug-input-prompt-regexp "(+rdb:\\([0-9]+\\|post-mortem\\)) " + "Regular expression to recognize a rdebug prompt. Some uses may prepend an anchor to the front.") + +(provide 'rdebug-regexp) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-regexp.el ends here diff --git a/emacs/.svn/text-base/rdebug-secondary.el.svn-base b/emacs/.svn/text-base/rdebug-secondary.el.svn-base new file mode 100644 index 0000000..3588bd5 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-secondary.el.svn-base @@ -0,0 +1,260 @@ +;;; rdebug-secondary.el --- Rdebug support windows. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; Key bindings and menu for secondary buffers. + +;;; Code: + +(require 'rdebug) + +(defun rdebug-populate-secondary-buffer-map (map) + "Bind all common keys and menu used in the rdebug secondary buffers. +This includes the keys bound to `gud-key-prefix' (typically C-x +C-a)." + (rdebug-populate-secondary-buffer-map-plain map) + (rdebug-populate-common-keys map) + (rdebug-populate-debugger-menu map) + (let ((prefix-map (make-sparse-keymap))) + (rdebug-populate-secondary-buffer-map-plain prefix-map) + (define-key map gud-key-prefix prefix-map))) + + +(defun rdebug-display-cmd-buffer () + "Display the rdebug debugger command buffer." + (interactive) + (rdebug-display-secondary-buffer "cmd")) + +(defun rdebug-pick-secondary-window-categorize (win name orig-win) + "Return how suiteable this window is to display the a secondary buffer. +The higher score the better." + (let ((buffer (window-buffer win))) + (save-current-buffer + (set-buffer buffer) + (cond (rdebug-secondary-buffer + (cond ((eq win orig-win) + ;; If the user issued the command inside a + ;; secondary window, use that window. + 5) + ((and (member name '("variables" "watch")) + (memq major-mode '(rdebug-variables-mode + rdebug-watch-mode))) + ;; Let "Watch" and "Variables" switch content. + 4) + (t + ;; Any other secondary window. + 3))) + ((eq major-mode 'ruby-mode) + ;; Avoid source windows. + 0) + ((eq major-mode 'gud-mode) + ;; Avoid the debugger shell window. + 1) + (t + ;; Just any other window. + 2))))) + + +(defun rdebug-display-secondary-buffer (name) + "Display one of the rdebug secondary buffers. +If the buffer doesn't exist, do nothing. If the buffer is already +displayed, switch to it. Otherwise if the current buffer is a +secondary buffer, bury it replacing with the requested +buffer. Failing that, if there is secondary buffer visible, that +is replaced instead. And finally failing all of the preceding, +we'll just pick a visible buffer to bury and replace." + (let* ((buf-name (rdebug-get-secondary-buffer-name name)) + (buf (get-buffer buf-name)) + (orig-win (selected-window))) + (if (null buf) + (message "Buffer %s not found" buf-name) + ;; Find a suitable window to display the buffer in. + (let ((win (get-buffer-window buf (selected-frame)))) + (if win + ;; Buffer already displayed, switch to it. + (select-window win) + ;; + (let ((candidate nil) + (candidate-score -1)) + (dolist (win (window-list (selected-frame))) + (let ((score (rdebug-pick-secondary-window-categorize + win name orig-win))) + (if (> score candidate-score) + (progn + (setq candidate win) + (setq candidate-score score))))) + (select-window candidate))))) + (switch-to-buffer buf))) + + +;; Note: The generic `gud' framework contains special code to handle +;; this for GDB (see `gud-display-line') which we, unfortuately can't +;; use. Instead, we call `rdebug-pick-source-window' from +;; `gud-rdebug-marker-filter'. When gud becomes more generic we could +;; hopefully solve this in another way. +;; +;; The machanism is that `rdebug-pick-source-window' displays the +;; source file in the window of our choice, and gud kindly re-uses +;; that window. + + +(defun rdebug-display-source-window-categorize (win) + "Return how suitable this window WIN is to display the source buffer. +The higher score the better." + (let ((buffer (window-buffer win))) + (cond ((eq buffer gud-comint-buffer) + 0) + ((buffer-local-value 'rdebug-secondary-buffer buffer) + 1) + ((eq (buffer-local-value 'major-mode buffer) 'ruby-mode) + 3) ; Pick me! Pick me! + (t + 2)))) + +(defun rdebug-display-pick-source-window () + "Return the window that should get replaced by the source window." + (rdebug-debug-enter "rdebug-display-pick-source-window" + (let ((candidate nil) + (candidate-score -1)) + (dolist (win (window-list (selected-frame))) + (let ((score + (rdebug-display-source-window-categorize win))) + (if (> score candidate-score) + (progn + (setq candidate win) + (setq candidate-score score))))) + candidate))) + +(defun rdebug-frame-source-buffer (frame) + "Return the buffer corresponding to the source file given in FRAME, or nil if none." + (and frame + gud-comint-buffer + (save-current-buffer + (set-buffer gud-comint-buffer) + (gud-find-file (car frame))))) + + +(defun rdebug-current-source-buffer () + "Return the latest source buffer, or nil." + (or (rdebug-frame-source-buffer gud-last-frame) + (rdebug-frame-source-buffer gud-last-last-frame))) + + +(defun rdebug-display-source-buffer () + "Display the current source buffer." + (interactive) + (rdebug-debug-enter "rdebug-display-source-buffer" + (let ((buffer (rdebug-current-source-buffer)) + (last-buffer (rdebug-frame-source-buffer gud-last-last-frame))) + (if buffer + (let ((window + (or + ;; Buffer is already visible, re-use the window. + (get-buffer-window buffer) + ;; Re-use the last window + (and last-buffer + (get-buffer-window last-buffer)) + ;; Find a non-rdebug window. + (rdebug-display-pick-source-window)))) + (select-window window) + (switch-to-buffer buffer)))))) + + +(defun rdebug-pick-source-window () + "Display the source file, but do not switch window." + (save-selected-window + (rdebug-display-source-buffer))) + + +(defun rdebug-display-source-buffer-resync () + "Resync output and display the source buffer." + (interactive) + (call-interactively 'gud-source-resync) + (rdebug-display-source-buffer)) + + +(defun rdebug-delete-frame-or-window () + "Delete frame if there is only one window. Otherwise delete the window." + (interactive) + (if (one-window-p) (delete-frame) + (delete-window))) + +(defun rdebug-goto-entry-try (str) + "See if thre is an entry with number STR. If not return nil." + (goto-char (point-min)) + (if (re-search-forward (concat "^[^0-9]*\\(" str "\\)[^0-9]") nil t) + (progn + (goto-char (match-end 1)) + t) + nil)) + + +;; The following is split in two to facilitate debugging. +(defun rdebug-goto-entry-n-internal (keys) + (if (and (stringp keys) + (= (length keys) 1)) + (progn + (setq rdebug-goto-entry-acc (concat rdebug-goto-entry-acc keys)) + ;; Try to find the longest suffix. + (let ((acc rdebug-goto-entry-acc) + (p (point))) + (while (not (string= acc "")) + (if (not (rdebug-goto-entry-try acc)) + (setq acc (substring acc 1)) + (setq p (point)) + ;; Break loop. + (setq acc ""))) + (goto-char p))) + (message "`rdebug-goto-entry-n' must be bound to a number key"))) + + +(defun rdebug-goto-entry-n () + "Go to an entry number. + +Breakpoints, Display expressions and Stack Frames all have +numbers associated with them which are distinct from line +numbers. In a secondary buffer, this function is usually bound to +a numeric key which will position you at that entry number. To +go to an entry above 9, just keep entering the number. For +example, if you press 1 and then 9, you should jump to entry +1 (if it exists) and then 19 (if that exists). Entering any +non-digit will start entry number from the beginning again." + (interactive) + (if (not (eq last-command 'rdebug-goto-entry-n)) + (setq rdebug-goto-entry-acc "")) + (rdebug-goto-entry-n-internal (this-command-keys))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-secondary) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-secondary.el ends here diff --git a/emacs/.svn/text-base/rdebug-shortkey.el.svn-base b/emacs/.svn/text-base/rdebug-shortkey.el.svn-base new file mode 100644 index 0000000..42bbbb7 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-shortkey.el.svn-base @@ -0,0 +1,175 @@ +;;; rdebug-watch.el --- Ruby debugger (short and simple) key bindings +;;; and minor mode. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file contains code which add short simple key bindings to buffers +;; which are part of an part of an rdebug session. It also handles +;; minor mode setting of these buffers. + +;;; Code: +;; ------------------------------------------------------------------- +;; Source short key mode. +;; +;; When this minor mode is active and the debugger is running, the +;; source window displaying the current debugger frame is marked as +;; read-only and the short keys of the secondary windows can be used, +;; for example, you can use the space-bar to single-step the program. + +;; Implementation note: +;; +;; This is presented to the user as one global minor mode. However, +;; under the surface the real work is done by another, non-global, +;; minor mode named "local short key mode". This is activated and +;; deactivated appropriately by the Rdebug filter functions. + +;; Implementation note: This is the user-level command. It only +;; controls if `rdebug-internal-short-key-mode' should be activated or +;; not. + +(require 'rdebug-source) + +(define-minor-mode rdebug-short-key-mode + "When enabled, short keys can be used in source buffers in `rdebug'." + :group 'rdebug + :global t + :init-value nil + ;; Unless the debugger is running, activating this doesn't do + ;; anything. + (if (featurep 'rdebug-core) + (with-no-warnings + (rdebug-short-key-mode-maybe-activate)))) + +(defvar rdebug-internal-short-key-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "b" 'gud-break) + (define-key map "t" 'rdebug-toggle-source-breakpoint-enabled) + (define-key map [insert] 'rdebug-short-key-mode) + ;;(define-key map "p" 'gud-print) + (rdebug-populate-secondary-buffer-map-plain map) + map) + "Keymap used in `rdebug-internal-short-key-mode'.") + +(defvar rdebug-original-read-only nil + "The value `buffer-read-only' should be restored to after short key mode.") + +;; `define-minor-mode' does not set if the mode was on or off prior to being called. +(defvar rdebug-internal-short-key-mode-previous-state nil + "Used to determine when 'rdebug-internal-short-key-mode' changed state.") + +;; Implementation note: This is the mode that does all the work, it's +;; local to the buffer that is affected. +(define-minor-mode rdebug-internal-short-key-mode + "Minor mode with short keys for source buffers for the `rdebug' debugger. +The buffer is read-only when the minor mode is active. + +Note that this is for internal use only, please use the global +mode `rdebug-short-key-mode'. + +\\{rdebug-internal-short-key-mode-map}" + :group 'rdebug + :global nil + :init-value nil + :lighter " ShortKeys" + :keymap rdebug-internal-short-key-mode-map + (make-local-variable 'rdebug-original-read-only) + (make-local-variable 'rdebug-internal-short-key-mode-previous-state) + ;; Ensure action only is performed when the state actually is toggled. + (unless (eq rdebug-internal-short-key-mode-previous-state + rdebug-internal-short-key-mode) + (if rdebug-internal-short-key-mode + ;; Mode is being turned on. + (progn + (setq rdebug-original-read-only buffer-read-only) + (setq buffer-read-only t)) + ;; Mode is being turned off. + (setq buffer-read-only rdebug-original-read-only)) + ;; Save the current state, so we can determine when the state is + ;; toggled in the future. + (setq rdebug-internal-short-key-mode-previous-state + rdebug-internal-short-key-mode))) + +(defun rdebug-buffer-killed-p (buffer) + "Return t if BUFFER is killed." + (not (buffer-name buffer))) + +(defun rdebug-internal-short-key-mode-on () + "Turn on `rdebug-internal-short-key-mode' in the current debugger frame." + (rdebug-debug-enter "rdebug-internal-short-key-mode-on" + (save-current-buffer + (if (and gud-comint-buffer + (not (rdebug-buffer-killed-p gud-comint-buffer))) + (set-buffer gud-comint-buffer)) + (let ((frame (or gud-last-frame + gud-last-last-frame))) + (if (and frame + rdebug-short-key-mode) + (ignore-errors + ;; `gud-find-file' calls `error' if it doesn't find the file. + (let ((buffer (gud-find-file (car frame)))) + (save-current-buffer + (set-buffer buffer) + ;; Make gud-comint-buffer local + (if gud-comint-buffer + (make-local-variable 'gud-comint-buffer)) + (rdebug-internal-short-key-mode 1))))))))) + + +(defun rdebug-turn-on-short-key-mode () + "Turn on `rdebug-short-key-mode'. + +This function is designed to be used in a user hook, for example: + + (add-hook 'rdebug-mode-hook 'rdebug-turn-on-short-key-mode)" + (interactive) + (rdebug-short-key-mode 1)) + + +(defun rdebug-turn-off-short-key-mode () + "Turn off `rdebug-short-key-mode'." + (interactive) + (rdebug-short-key-mode -1)) + + +(defun rdebug-short-key-mode-maybe-activate () + (if rdebug-short-key-mode + (rdebug-internal-short-key-mode-on) + (rdebug-internal-short-key-mode-off))) + + +(defun rdebug-internal-short-key-mode-off () + "Turn off `rdebug-internal-short-key-mode' in all buffers." + (rdebug-debug-enter "rdebug-internal-short-key-mode-off" + (save-current-buffer + (dolist (buf (buffer-list)) + (set-buffer buf) + (when rdebug-internal-short-key-mode + (rdebug-internal-short-key-mode -1)))))) + +(provide 'rdebug-shortkey) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-shortkey.el ends here diff --git a/emacs/.svn/text-base/rdebug-source.el.svn-base b/emacs/.svn/text-base/rdebug-source.el.svn-base new file mode 100644 index 0000000..b3cb7e9 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-source.el.svn-base @@ -0,0 +1,568 @@ +;;; rdebug-source.el --- Ruby debugger user interface. + +;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file is loaded when a Ruby source buffer is loaded. It +;; contains, among else, the Debugger menu. + +;;; Code: + +;; ------------------------------------------------------------------- +;; Consistency checks. +;; + +(if (< emacs-major-version 22) + (error + "Rdebug needs at least Emacs 22 or greater - you have version %d." + emacs-major-version)) + + +;; ------------------------------------------------------------------- +;; Dependencies. +;; + +(require 'cl) + +(require 'gud) ; For gud-key-prefix, sigh... +(require 'rdebug) +(require 'rdebug-vars) + + +;; ------------------------------------------------------------------- +;; Key bindings +;; + +(defun rdebug-populate-common-keys-standard (map) + "Bind the basic debugger key layout used by many debuggers. + +\\{rdebug-example-map-standard}" + (define-key map [f5] 'gud-cont) + (define-key map [S-f5] 'rdebug-quit) + (define-key map [f9] 'rdebug-toggle-source-breakpoint) + (define-key map [C-f9] 'rdebug-toggle-source-breakpoint-enabled) + (define-key map [f10] 'rdebug-next) + (define-key map [f11] 'rdebug-step) + (define-key map [S-f11] 'gud-finish)) + + +;; TODO: Verify and complement. +(defun rdebug-populate-common-keys-eclipse (map) + "Bind the basic debugger key layout used by Eclipse. + +\\{rdebug-example-map-eclipse}" + ;;(define-key map [] 'gud-cont) + ;;(define-key map [] 'rdebug-quit) + (define-key map [S-C-b] 'rdebug-toggle-source-breakpoint) + (define-key map [f6] 'rdebug-next) + (define-key map [f5] 'rdebug-step) + (define-key map [f7] 'gud-finish)) + + +;; TODO: Verify and complement. +(defun rdebug-populate-common-keys-netbeans (map) + "Bind the basic debugger key layout used by NetBeans. + +\\{rdebug-example-map-netbeans}" + ;;(define-key map [] 'gud-cont) + ;;(define-key map [] 'rdebug-quit) + ;; F4 - Run to cursor. + (define-key map [S-f8] 'rdebug-toggle-source-breakpoint) + (define-key map [f8] 'rdebug-next) + (define-key map [f7] 'rdebug-step) + (define-key map [M-S-f7] 'gud-finish)) + + +;; Note: This is only used in doc-strings. +(defvar rdebug-example-map-standard + (let ((map (make-sparse-keymap))) + (rdebug-populate-common-keys-standard map) + map) + "Rdebug Standard common keymap used only in doc-string.") + + +(defvar rdebug-example-map-eclipse + (let ((map (make-sparse-keymap))) + (rdebug-populate-common-keys-eclipse map) + map) + "Rdebug Eclipse compatibility common keymap used only in doc-string.") + + +(defvar rdebug-example-map-netbeans + (let ((map (make-sparse-keymap))) + (rdebug-populate-common-keys-netbeans map) + map) + "Rdebug NetBeans compatibility common keymap used only in doc-string.") + + +(defun rdebug-populate-common-keys (map) + "Define the keys that are used by all debugger windows, even by the source. + +The variable `rdebug-populate-common-keys-function' controls the layout." + (define-key map "\C-x\C-a\C-q" 'rdebug-short-key-mode) + (if rdebug-populate-common-keys-function + (funcall rdebug-populate-common-keys-function map))) + + +(defun rdebug-populate-digit-keys (map) + (define-key map "0" 'rdebug-goto-entry-n) + (define-key map "1" 'rdebug-goto-entry-n) + (define-key map "2" 'rdebug-goto-entry-n) + (define-key map "3" 'rdebug-goto-entry-n) + (define-key map "4" 'rdebug-goto-entry-n) + (define-key map "5" 'rdebug-goto-entry-n) + (define-key map "6" 'rdebug-goto-entry-n) + (define-key map "7" 'rdebug-goto-entry-n) + (define-key map "8" 'rdebug-goto-entry-n) + (define-key map "9" 'rdebug-goto-entry-n)) + + +;; ------------------------------------------------------------------- +;; Menu support. +;; + + +;; Note: We want the key binding to show in the menu. However, our +;; situation is a little bit complex: +;; +;; 1) We want the binding of the `common' man (i.e. the function key +;; the user has selected.) +;; +;; 2) We want this even when the menu is disabled and the key isn't +;; bound, typically when the debugger isn't running. +;; +;; This has been solved by setting up an explicit ":keys" properly. +(defun rdebug-menu-item (common-map name cmd &rest args) + "Return a menu item entry with the correct key bindings. + +A command can be bound to a number of different key sequences. If +the rdebug common map contains a binding it is displayed in the +menu. (The common map typically contains function key bindings.)" + (let ((key-binding (where-is-internal cmd (list common-map) t)) + (hint '())) + (if key-binding + (setq hint (list :keys (key-description key-binding)))) + (append (list 'menu-item name cmd) + hint + args))) + + +;; Note, we re-populate the menus of the different minor and major +;; modes. The reason is that Emacs caches the key bindings, which +;; means that wrong ones are shown when buffers are changed. + +;; Remember, all menu items are added in the reverse order! + +(defun rdebug-populate-debugger-menu (map) + "Populate the Rdebug 'Debugger' menu." + (let ((menu (make-sparse-keymap)) + (common-map (make-sparse-keymap))) + ;; Use a simple common map to find the best key sequence to + ;; display in menu. + (rdebug-populate-common-keys common-map) + + (define-key map [menu-bar debugger] (cons "Debugger" menu)) + + (define-key menu [break-delete] + (rdebug-menu-item common-map "Enable/disable breakpoint" + 'rdebug-toggle-source-breakpoint-enabled + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [break] + (rdebug-menu-item common-map "Toggle breakpoint" + 'rdebug-toggle-source-breakpoint + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [finish] + (rdebug-menu-item common-map "Step out" 'gud-finish + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [step] + (rdebug-menu-item common-map "Step into" 'rdebug-step + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [next] + (rdebug-menu-item common-map "Step over" 'rdebug-next + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [cont] + (rdebug-menu-item common-map "Continue" 'rdebug-continue + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger line1] '(menu-item "--")) + + (define-key menu [stop] + (rdebug-menu-item + common-map "Stop the debugger" 'rdebug-quit + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [start] + (rdebug-menu-item common-map "Start the debugger" 'rdebug)) + + (define-key map [menu-bar debugger line2] '(menu-item "--")) + + ;; -------------------- + ;; The "Options" submenu. + + (let ((submenu (make-sparse-keymap))) + (define-key menu [options] (cons "Options" submenu))) + + (define-key map [menu-bar debugger options customize] + (rdebug-menu-item common-map + "Customize Rdebug" 'rdebug-customize)) + + (define-key map [menu-bar debugger options line1] '(menu-item "--")) + + + + ;; ---------------- + ;; The "short key" toggle. + + (define-key map [menu-bar debugger options short-key-mode] + (rdebug-menu-item common-map + "Short keys in source" 'rdebug-short-key-mode + :button + '(:toggle + . rdebug-short-key-mode))) + + (define-key map [menu-bar debugger options line2] '(menu-item "--")) + + ;; ---------------- + ;; Separate I/O buffer. + + (define-key map [menu-bar debugger options io-buffer] + (rdebug-menu-item common-map + "Separate I/O buffer" + 'rdebug-toggle-use-separate-io-buffer + :button + '(:toggle + . rdebug-use-separate-io-buffer))) + + ;; -------------------- + ;; The optional secondary windows submenu. + + + ;; Placeholder used when populating the menu of the secondary buffers. + (define-key menu [placeholder] nil) + + ;; -------------------- + ;; The "Window Layout" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key menu [layout] (cons "Window Layout" submenu))) + + ;; ---------------- + ;; The "Window Layout" submenu. + + + ;; TODO: The following is a somewhat clumsy implementation. Maybe we can + ;; automatically generate the entries, or use the `dynamic' menu kind? + ;; + ;; Also, there might be other situations where the list might be + ;; handy, e.g. completion. + (let ((predefined '(rdebug-window-layout-standard + rdebug-window-layout-no-shell + rdebug-window-layout-conservative + rdebug-window-layout-stack-of-windows + rdebug-window-layout-rocky + rdebug-window-layout-rocky2))) + + (define-key map [menu-bar debugger layout other] + (rdebug-menu-item + common-map + "Other" + 'rdebug-set-window-layout + :button + `(:radio + . (not (memq rdebug-window-layout-function (quote ,predefined)))))) + + (define-key map [menu-bar debugger layout rocky] + (rdebug-menu-item + common-map + "Rocky's Own" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-rocky)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-rocky)))) + + (define-key map [menu-bar debugger layout rocky2] + (rdebug-menu-item + common-map + "Rocky II" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-rocky2)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-rocky2)))) + + (define-key map [menu-bar debugger layout stack] + (rdebug-menu-item + common-map + "Stack of Windows" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-stack-of-windows)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-stack-of-windows)))) + + (define-key map [menu-bar debugger layout conservative] + (rdebug-menu-item + common-map + "Conservative" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-conservative)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-conservative)))) + + (define-key map [menu-bar debugger layout no-shell] + (rdebug-menu-item + common-map + "No Shell" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-no-shell)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-no-shell)))) + + (define-key map [menu-bar debugger layout standard] + (rdebug-menu-item + common-map + "Standard" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-standard)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-standard))))) + + (define-key map [menu-bar debugger layout line3] '(menu-item "--")) + + (define-key map [menu-bar debugger layout initial] + (rdebug-menu-item common-map + "Restore Debugger Layout" + 'rdebug-restore-debugger-window-layout + :enable '(fboundp 'rdebug-restore-debugger-window-layout))) + + (define-key map [menu-bar debugger layout line1] '(menu-item "--")) + + ;; Note: It seems as though :enable doesn't work when :button is used. + (define-key map [menu-bar debugger layout debugger] + (rdebug-menu-item common-map "Current Debugger Layout" + 'rdebug-display-debugger-window-configuration + :button + '(:radio + . (eq rdebug-window-configuration-state 'debugger)))) + + (define-key map [menu-bar debugger layout original] + (rdebug-menu-item common-map "Original Layout" + 'rdebug-display-original-window-configuration + :button + '(:radio + . (eq rdebug-window-configuration-state 'original)))) + + ;; -------------------- + ;; The "View" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key menu [view] (cons "View" submenu))) + + (define-key map [menu-bar debugger view output] + (rdebug-menu-item common-map "Output" 'rdebug-display-output-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view watch] + (rdebug-menu-item common-map "Watch" 'rdebug-display-watch-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view stack] + (rdebug-menu-item common-map "Stack-Frame trace" + 'rdebug-display-frame-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view shell] + (rdebug-menu-item common-map "Debugger Shell" 'rdebug-display-cmd-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view variables] + (rdebug-menu-item common-map "Variables" 'rdebug-display-variables-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view breakpoints] + (rdebug-menu-item common-map + "Breakpoints" 'rdebug-display-breakpoints-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view source] + (rdebug-menu-item common-map + "Source" 'rdebug-display-source-buffer + :enable '(get-buffer-process gud-comint-buffer))) + menu)) + + +;; ----------------------------------------------- +;; Key bindings and menu for secondary buffers. +;; + +(defun rdebug-populate-secondary-buffer-map-plain (map) + "Bind the plain keys used in rdebug secondary buffers. + +This does not menus or prefix keys." + ;; Keys to view other buffers. + (let ((prefix-map (make-sparse-keymap))) + (define-key map "?" 'rdebug-display-secondary-window-help-buffer) + (define-key map "B" 'rdebug-display-breakpoints-buffer) + (define-key map "C" 'rdebug-display-cmd-buffer) + (define-key map "E" 'rdebug-display-error-buffer) + (define-key map "F" 'rdebug-display-frame-buffer) + (define-key map "I" 'rdebug-display-info-buffer) + (define-key map "O" 'rdebug-display-output-buffer) + (define-key map "S" 'rdebug-display-source-buffer) + (define-key map "V" 'rdebug-display-variables-buffer) + (define-key map "W" 'rdebug-display-watch-buffer) + ;; Common debugger commands. + (define-key map " " 'rdebug-step) + (define-key map "_" 'rdebug-set-stepping-prefix) + (define-key map "+" 'rdebug-set-stepping-prefix) + (define-key map "-" 'rdebug-set-stepping-prefix) + (define-key map "<" 'rdebug-newer-frame) + (define-key map ">" 'rdebug-older-frame) + ;; (define-key map "a" 'gud-args) + ;; (define-key map "b" 'gud-break) + (define-key map "c" 'rdebug-continue) + ;; (define-key map "d" 'gud-remove) + (define-key map "f" 'gud-finish) + (define-key map "n" 'rdebug-next) + (define-key map "p" prefix-map) + (define-key map "q" 'rdebug-quit) + (define-key map "r" 'rdebug-restart) + (define-key map "R" 'rdebug-restart) + (define-key map "s" 'rdebug-step) + (define-key map [M-down] 'rdebug-locring-newer) + (define-key map [M-up] 'rdebug-locring-older) + (define-key map [M-S-down] 'rdebug-locring-newest) + (define-key map [M-S-up] 'rdebug-locring-oldest) + (define-key map [mouse-3] 'rdebug-variables-pretty-print-mouse) + (define-key prefix-map "l" 'rdebug-print-list-region) + (define-key prefix-map "p" 'rdebug-pretty-print-region) + (define-key prefix-map "s" 'rdebug-print-sorted-region) + )) + + +;; ------------------------------------------------------------------- +;; Window layout. +;; + +;; This function is intended for the Options submenu. +(defun rdebug-set-window-layout (func) + "Set and, if the debugger is running, display the window layout." + (interactive "aWindow layout function: ") + (setq rdebug-window-layout-function func) + (if gud-comint-buffer + (with-no-warnings + (rdebug-setup-windows)))) + + +;; ------------------------------------------------------------------- +;; The source buffer rdebug support mode. +;; +;; This is a minor mode that is active in Ruby source buffers. It +;; provides the menu and, when the debugger is active, the debugger +;; key bindings. + +(defvar rdebug-debugger-support-minor-mode-map-when-deactive + (let ((map (make-sparse-keymap)) + (prefix-map (make-sparse-keymap))) + (rdebug-populate-debugger-menu map) + (rdebug-populate-secondary-buffer-map-plain prefix-map) + (define-key map gud-key-prefix prefix-map) + map) + "Keymap used by rdebugs support minor mode when the debugger is active.") + +(defvar rdebug-debugger-support-minor-mode-map-when-active + (let ((map (make-sparse-keymap)) + (prefix-map (make-sparse-keymap))) + (rdebug-populate-debugger-menu map) + (rdebug-populate-secondary-buffer-map-plain prefix-map) + (define-key prefix-map [insert] 'rdebug-short-key-mode) + (define-key map gud-key-prefix prefix-map) + (rdebug-populate-common-keys map) + map) + "Keymap used by rdebugs support minor mode when the debugger not active.") + + +(define-minor-mode rdebug-debugger-support-minor-mode + "Minor mode active in source buffers that use the `rdebug' Ruby debugger." + :group rdebug + :global nil + :init-value nil + :keymap rdebug-debugger-support-minor-mode-map-when-deactive + (setq mode-line-process (and rdebug-debugger-support-minor-mode + 'rdebug-mode-line-process))) + + +;;;###autoload +(defun rdebug-turn-on-debugger-support () + "Enable extra source buffer support for the `rdebug' Ruby debugger. + +This includes a 'Debugger' menu and special key bindings when the +debugger is active." + (rdebug-debugger-support-minor-mode 1)) + + +;; ------------------------------------------------------------------- +;; Use separate I/O buffer +;; + +(defun rdebug-toggle-use-separate-io-buffer () + "Toggle `rdebug-use-separate-io-buffer'. +This is used by the menu." + (interactive) + (setq rdebug-use-separate-io-buffer (not rdebug-use-separate-io-buffer)) + (if (interactive-p) + (message "Issue M-x rdebug-restore-debugger-window-layout \ +RET to update display."))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-source) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-source.el ends here diff --git a/emacs/.svn/text-base/rdebug-track.el.svn-base b/emacs/.svn/text-base/rdebug-track.el.svn-base new file mode 100644 index 0000000..78b0523 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-track.el.svn-base @@ -0,0 +1,392 @@ +;;; rdebug-track.el --- Tracking the Ruby debugger from a shell +;; $Id$ + +;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren +;; Modified from python-mode in particular the part: +;; pdbtrack support contributed by Ken Manheimer, April 2001. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; `rdebug-track-mode' allows access to full debugger user interface +;; for Ruby debugger sessions started in a standard shell window. +;; `turn-on-rdebug-track-mode' turns the mode on and +;; `turn-off-rdebug-track-mode' turns it off. +;; +;;; Customization: +;; `rdebug-track' sets whether file tracking is done by the shell prompt. +;; `rdebug-track-minor-mode-string' sets the mode indicator to show that +;; tracking is in effect. +;; + +;;; Code: + +;; ------------------------------------------------------------------- +;; Customizable variables. +;; + +(defgroup rdebug-track nil + "Ruby debug and rdebug file tracking by watching the shell prompt." + :prefix "rdebug-track" + :group 'shell) + +(defcustom rdebug-track-do-tracking-p nil + "*Controls whether the rdebug-track feature is enabled or not. +When non-nil, rdebug-track is enabled in all comint-based buffers, +e.g. shell buffers and the *Ruby* buffer. When using rdebug to debug a +Ruby program, rdebug-track notices the rdebug prompt and displays the +source file and line that the program is stopped at, much the same way +as gud-mode does for debugging C programs with gdb." + :type 'boolean + :group 'rdebug) +(make-variable-buffer-local 'rdebug-track-do-tracking-p) + +(defcustom rdebug-track-minor-mode-string " rdebug" + "*String to use in the minor mode list when rdebug-track is enabled." + :type 'string + :group 'rdebug) + + +;; ------------------------------------------------------------------- +;; Variables. +;; + +(defvar gud-rdebug-history nil + "History of argument lists passed to rdebug.") + +;; rdebug-track constants +(defconst rdebug-track-stack-entry-regexp + "^(\\([-a-zA-Z0-9_/.]*\\):\\([0-9]+\\)):[ \t]?\\(.*\n\\)" + "Regular expression rdebug-track uses to find a stack trace entry.") + +(defconst rdebug-track-track-range 10000 + "Max number of characters from end of buffer to search for stack entry.") + + +;; ------------------------------------------------------------------- +;; Dependencies. +;; + +(require 'comint) +(require 'custom) +(require 'cl) +(require 'compile) +(require 'gud) +(require 'shell) +(require 'rdebug-breaks) +(require 'rdebug-cmd) +(require 'rdebug-core) + + +;; ------------------------------------------------------------------- +;; Rdebug track -- support for attaching the `rdebug' ruby debugger to +;; a process running in a shell buffer. +;; + +(defvar rdebug-track-is-tracking-p t) + +(defun rdebug-track-overlay-arrow (activation) + "Activate or de arrow at beginning-of-line in current buffer." + ;; This was derived/simplified from edebug-overlay-arrow + (cond (activation + (setq overlay-arrow-position (make-marker)) + (setq overlay-arrow-string "=>") + (set-marker overlay-arrow-position (point) (current-buffer)) + (setq rdebug-track-is-tracking-p t)) + (rdebug-track-is-tracking-p + (setq overlay-arrow-position nil) + (setq rdebug-track-is-tracking-p nil)) + )) + +(defun rdebug-track-track-stack-file (text) + "Show the file indicated by the rdebug stack entry line, in a separate window. +Activity is disabled if the buffer-local variable +`rdebug-track-do-tracking-p' is nil. + +We depend on the rdebug input prompt matching `rdebug-input-prompt-regexp' +at the beginning of the line." + ;; Instead of trying to piece things together from partial text + ;; (which can be almost useless depending on Emacs version), we + ;; monitor to the point where we have the next rdebug prompt, and then + ;; check all text from comint-last-input-end to process-mark. + ;; + ;; Also, we're very conservative about clearing the overlay arrow, + ;; to minimize residue. This means, for instance, that executing + ;; other rdebug commands wipe out the highlight. You can always do a + ;; 'where' (aka 'w') command to reveal the overlay arrow. + (rdebug-debug-enter "rdebug-track-track-stack-file" + (let* ((origbuf (current-buffer)) + (currproc (get-buffer-process origbuf))) + + (if (not (and currproc rdebug-track-do-tracking-p)) + (rdebug-track-overlay-arrow nil) + ;;else + (let* ((procmark (process-mark currproc)) + (block-start (max comint-last-input-end + (- procmark rdebug-track-track-range))) + (block-str (buffer-substring block-start procmark)) + target target_fname target_lineno target_buffer) + + (if (not (string-match rdebug-input-prompt-regexp block-str)) + (rdebug-track-overlay-arrow nil) + ;;else + (setq target (rdebug-track-get-source-buffer block-str)) + + (if (stringp target) + (rdebug-debug-message "rdebug-track: %s" target) + ;;else + (gud-rdebug-marker-filter block-str) + (setq target_lineno (car target)) + (setq target_buffer (cadr target)) + (setq target_fname (buffer-file-name target_buffer)) + (setq gud-last-frame (cons target_fname target_lineno)) + (switch-to-buffer-other-window target_buffer) + (goto-line target_lineno) + (rdebug-debug-message "rdebug-track: line %s, file %s" + target_lineno target_fname) + (rdebug-track-overlay-arrow t) + (rdebug-set-frame-top-arrow (current-buffer)) + (set (make-local-variable 'gud-comint-buffer) origbuf) + (set (make-local-variable 'gud-delete-prompt-marker) + (make-marker)) + (pop-to-buffer origbuf t) + (rdebug-locring-add gud-last-frame + rdebug-source-location-ring)) + + ;; Delete processed annotations from buffer. + (save-excursion + (let ((annotate-start) + (annotate-end (point-max))) + (goto-char block-start) + (while (re-search-forward + rdebug-annotation-start-regexp annotate-end t) + (let* ((start (match-beginning 0)) + (end (match-end 0)) + (name (or (match-string 1) "source"))) + (cond ((string= name "prompt\n") + (delete-region (- start 1) end)) + ((string= name "pre-prompt\n") + (delete-region start end)) + ((string= name "error-begin\n") + (delete-region start end)) + ((re-search-forward rdebug-annotation-end-regexp + annotate-end t) + (delete-region start (point))) + (t (forward-line))))))) + )))))) + +(defun rdebug-track-get-source-buffer (block-str) + "Return line and buffer of code indicated by block-str's traceback text. + +We look first to visit the file indicated in the trace. + +Failing that, we look for the most recently visited ruby-mode buffer +with the same name or having having the named function. + +If we're unable find the source code we return a string describing the +problem as best as we can determine." + + (if (not (string-match rdebug-position-regexp block-str)) + "line number cue not found" + ;;else + (let* ((filename (match-string rdebug-marker-regexp-file-group block-str)) + (lineno (string-to-number + (match-string rdebug-marker-regexp-line-group block-str))) + funcbuffer) + + (cond ((file-exists-p filename) + (list lineno (find-file-noselect filename))) + + ((= (elt filename 0) ?\<) + (format "(Non-file source: '%s')" filename)) + + (t (format "Not found: %s" filename)))))) + + + +;; ----------------------------------------------- +;; Rdebug track mode +;; + + +(defcustom rdebug-track-mode-text " rdebug" + "*String to display in the mode line when rdebug-track mode is active. + +\(When the string is not empty, make sure that it has a leading space.)" + :tag "rdebug mode text" ; To separate it from `global-...' + :group 'rdebug + :type 'string) + +(define-minor-mode rdebug-track-mode + "Minor mode for tracking ruby debugging inside a process shell." + :init-value nil + ;; The indicator for the mode line. + :lighter rdebug-track-mode-text + ;; The minor mode bindings. + :global nil + :group 'rdebug + (rdebug-track-toggle-stack-tracking 1) + (setq rdebug-track-is-tracking-p t) + (local-set-key "\C-cg" 'rdebug-goto-traceback-line) + (local-set-key "\C-cG" 'rdebug-goto-dollarbang-traceback-line) + + (add-hook 'comint-output-filter-functions 'rdebug-track-track-stack-file) + (run-mode-hooks 'rdebug-track-mode-hook)) + + +(defun rdebug-track-toggle-stack-tracking (arg) + (interactive "P") + (if (not (get-buffer-process (current-buffer))) + (message "No process associated with buffer '%s'" (current-buffer)) + ;;else + ;; missing or 0 is toggle, >0 turn on, <0 turn off + (if (or (not arg) + (zerop (setq arg (prefix-numeric-value arg)))) + (setq rdebug-track-do-tracking-p (not rdebug-track-do-tracking-p)) + (setq rdebug-track-do-tracking-p (> arg 0))) + (message "%sabled rdebug's rdebug-track" + (if rdebug-track-do-tracking-p "En" "Dis")))) + + +;;;###autoload +(defun turn-on-rdebug-track-mode () + "Turn on rdebug-track mode. + +This function is designed to be added to hooks, for example: + (add-hook 'comint-mode-hook 'turn-on-rdebug-track-mode)" + (interactive) + (set (make-local-variable 'gud-last-last-frame) nil) + (set (make-local-variable 'gud-last-frame) nil) + (set (make-local-variable 'gud-comint-buffer) (current-buffer)) + + (set (make-local-variable 'gud-marker-filter) 'gud-rdebug-marker-filter) + (set (make-local-variable 'gud-minor-mode) 'rdebug) + (set (make-local-variable 'comint-prompt-regexp) (concat "^" rdebug-input-prompt-regexp)) + + (set (make-local-variable 'gud-find-file) 'gud-rdebug-find-file) + + (rdebug-command-initialization) + + (rdebug-track-mode 1)) + + +(defun turn-off-rdebug-track-mode () + "Turn off rdebug-track mode." + (interactive) + (setq rdebug-track-is-tracking-p nil) + + (rdebug-track-toggle-stack-tracking 0) + (if (local-variable-p 'gud-last-frame) + (setq gud-last-frame nil)) + (while (not (ring-empty-p rdebug-source-location-ring)) + (ring-remove rdebug-source-location-ring)) + (remove-hook 'comint-output-filter-functions + 'rdebug-track-track-stack-file)) + + +;; ----------------------------------------------- +;; The `attach' function. +;; + +(defun rdebug-track-attach (&optional name rename-shell) + "Do things to make the current process buffer work like a +rdebug command buffer. In particular, the buffer is renamed, +gud-mode is set, and rdebug-track-mode is turned on, among other +things. When `rdebug-many-windows' is non-nil, the initial debugger +window layout is used." + (interactive "sProgram name: ") + (rdebug-debug-enter "rdebug-set-windows" + (rdebug-set-window-configuration-state 'debugger t) + + ;; from rdebug-common-init + (gud-mode) + (set (make-local-variable 'gud-marker-filter) 'gud-rdebug-marker-filter) + (set (make-local-variable 'gud-minor-mode) 'rdebug) + (set (make-local-variable 'gud-last-frame) nil) + (set (make-local-variable 'gud-last-last-frame) nil) + + (set (make-local-variable 'gud-find-file) 'gud-rdebug-find-file) + (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter) + (gud-set-buffer) + ;; + + (rdebug-track-mode 1) + (rdebug-command-initialization) + + (when name + (if rename-shell + (rename-buffer (format "*rdebug-cmd-%s*" gud-target-name))) + (setq gud-target-name name) + (setq gud-comint-buffer (current-buffer))) + + ;; Setup exit callback so that the original frame configuration + ;; can be restored. + (let ((process (get-buffer-process gud-comint-buffer))) + (when process + (unless (equal rdebug-line-width 120) + (gud-call (format "set width %d" rdebug-line-width))) + (set-process-sentinel process + 'rdebug-process-sentinel))) + + (when gud-last-frame + (setq gud-last-last-frame gud-last-frame)) + + ;; Add the buffer-displaying commands to the Gud buffer, + ;; FIXME: combine with code in rdebug-track.el; make common + ;; command buffer mode map. + (let ((prefix-map (make-sparse-keymap)) + (map (current-local-map))) + (define-key map [M-down] 'rdebug-locring-newer) + (define-key map [M-up] 'rdebug-locring-older) + (define-key map [M-S-down] 'rdebug-locring-newest) + (define-key map [M-S-up] 'rdebug-locring-oldest) + (define-key map gud-key-prefix prefix-map) + (define-key prefix-map "t" 'rdebug-goto-traceback-line) + (define-key prefix-map "!" 'rdebug-goto-dollarbang-traceback-line) + + (rdebug-populate-secondary-buffer-map-plain prefix-map)) + + (rdebug-populate-common-keys (current-local-map)) + (rdebug-populate-debugger-menu (current-local-map)) + + (set (make-local-variable 'comint-prompt-regexp) (concat "^" rdebug-input-prompt-regexp)) + (setq paragraph-start comint-prompt-regexp) + + (setcdr (assq 'rdebug-debugger-support-minor-mode minor-mode-map-alist) + rdebug-debugger-support-minor-mode-map-when-active) + + (gud-call "set annotate 3") + (gud-call "frame 0") + (when rdebug-many-windows + (rdebug-setup-windows)) + (run-hooks 'rdebug-mode-hook))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-track) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-track.el ends here diff --git a/emacs/.svn/text-base/rdebug-varbuf.el.svn-base b/emacs/.svn/text-base/rdebug-varbuf.el.svn-base new file mode 100644 index 0000000..e94a8e7 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-varbuf.el.svn-base @@ -0,0 +1,150 @@ +;;; rdebug-varbuf.el --- This file contains code dealing with the Ruby +;;; debugger's "variables" secondary buffer. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;;; Code: + +(defvar rdebug-variables-mode-map + (let ((map (make-sparse-keymap))) + (suppress-keymap map) + (define-key map "\r" 'rdebug-variables-edit) + ;; (define-key map "e" 'rdebug-edit-variables-value) + (define-key map [mouse-2] 'rdebug-variables-edit-mouse) + (define-key map "e" 'rdebug-variables-print) + (define-key map "x" 'rdebug-variables-pretty-print) + (rdebug-populate-secondary-buffer-map map) + + ;; -------------------- + ;; The "Variables window" submenu. + + (let ((submenu (make-sparse-keymap))) + (define-key-after map [menu-bar debugger variables] + (cons "Variables window" submenu) + 'placeholder)) + + (define-key map [menu-bar debugger variables edit] + '(menu-item "Edit" rdebug-variables-edit + :enable (eq major-mode 'rdebug-variables-mode))) + + map) + "Keymap used in the variables buffer in the `rdebug' Ruby debugger.") + +(defvar rdebug-variables-font-lock-keywords + '(("@[a-zA-Z0-9_]+" 0 font-lock-variable-name-face) + ("\\<\\(nil\\|true\\|false\\)\\>" 0 font-lock-constant-face) + ("#<\\([a-zA-Z0-9_]+\\):\\([0-9a-fx]*\\)" + (1 font-lock-type-face) + (2 font-lock-constant-face))) + "Font-lock rules for the variables and watch windows in `rdebug'.") + +(defun rdebug-display-variables-buffer () + "Display the rdebug variables buffer." + (interactive) + (rdebug-display-secondary-buffer "variables")) + +(defun rdebug-variables-mode () + "Major mode for the variables buffer in the `rdebug' Ruby debugger. + +\\{rdebug-variables-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-variables-mode) + (setq mode-name "RDEBUG Variables") + (setq buffer-read-only t) + (setq truncate-lines t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (set (make-local-variable 'font-lock-defaults) + '(rdebug-variables-font-lock-keywords)) + (use-local-map rdebug-variables-mode-map) + (run-mode-hooks 'rdebug-variables-mode-hook)) + +(defun rdebug-setup-variables-buffer (buf comint-buffer) + (rdebug-debug-enter "rdebug-setup-variables-buffer" + (with-current-buffer buf + (rdebug-variables-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer)))) + +(defun rdebug-variables-edit-mouse (&optional event) + "Assign a value to a variable displayed in the variables buffer. +This function is intended to be bound to a mouse key" + (interactive (list last-input-event)) + (save-excursion + (if event (posn-set-point (event-end event))) + (call-interactively 'rdebug-variables-edit))) + +(defun rdebug-variables-edit (var value) + "Assign a value to a variable displayed in the variables buffer." + (interactive + (let ((var nil) + (value nil)) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\(@?[a-zA-Z_0-9]+\\) *= *\\(.*\\)$") + (setq var (match-string 1)) + (setq value (match-string 2)) + (setq value (read-from-minibuffer + (format "New value (%s): " var) value))) + (list var value)))) + (gud-call (format "p %s=%s" var value))) + +(defun rdebug-variables-pretty-print (var) + "Pretty print a variable in the variables buffer." + (interactive + (let ((var nil)) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\(@?[a-zA-Z_0-9]+\\) *= *\\(.*\\)$") + (setq var (match-string 1))) + (list var)))) + (rdebug-print-cmd var "pp")) + +(defun rdebug-variables-pretty-print-mouse (&optional event) + "Assign a value to a variable displayed in the variables buffer. +This function is intended to be bound to a mouse key" + (interactive (list last-input-event)) + (save-excursion + (if event (posn-set-point (event-end event))) + (call-interactively 'rdebug-variables-pretty-print))) + +(defun rdebug-variables-print (var) + "Print a variable in the variables buffer." + (interactive + (let ((var nil)) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\(@?[a-zA-Z_0-9]+\\) *= *\\(.*\\)$") + (setq var (match-string 1))) + (list var)))) + (rdebug-print-cmd var "p")) + +(provide 'rdebug-varbuf) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-varbuf.el ends here diff --git a/emacs/.svn/text-base/rdebug-vars.el.svn-base b/emacs/.svn/text-base/rdebug-vars.el.svn-base new file mode 100644 index 0000000..7688562 --- /dev/null +++ b/emacs/.svn/text-base/rdebug-vars.el.svn-base @@ -0,0 +1,125 @@ +;;; rdebug-var.el --- Ruby debugger variables (other than regexps) + +;; Copyright (C) 2007 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; +;; Introduction: +;; +;; This is a full-blown debugger user interface to the Ruby rdebug +;; debugger shell. +;; +;; Internal debug support. When `rdebug-debug-active' is non-nil, +;; internal debug messages are placed in the buffer *Xrdebug*. +;; Functions can be annotated with `rdebug-debug-enter' to display a +;; call trace. +;; + +;;; Code: + +(defvar rdebug-current-line-number 1 + "The line number in a secondary window that you were in. We need to save + this value because secondary windows get recreated a lot") + +(defvar rdebug-debug-active nil + "Non-nil when rdebug should emit internal debug output to *Xrdebug*.") + +;; Indentation depth of `rdebug-debug-enter'. +(defvar rdebug-debug-depth 0) + +(defvar rdebug-debugger-window-configuration nil + "The saved window layout of the debugger.") + +(defvar rdebug-frames-current-frame-number nil + "The frame number of the selected frame.") + +(defvar rdebug-goto-entry-acc "") + +(defvar rdebug-output-marker-number 0 + "Number to be used when `rdebug-output-add-divider' is next + called on the secondary output buffer.") + +(defvar rdebug-original-window-configuration nil + "The window layout rdebug should restore when the debugger exits.") + +;; Terminology: a "secondary buffer" is the physical emacs buffer, +;; which can be visible or invisible. A "secondary window", is a window +;; that rdebug is reusing to display different secondary buffers. +;; +;; For example, the "secondary-window-help" buffer is named the way it +;; is since it gives help on how the secondary window is used. +(defvar rdebug-secondary-buffer nil + "Non-nil for rdebug secondary buffers (e.g. the breakpoints buffer).") + +;; Currently, this is the "output" and "info" buffers. +(defvar rdebug-accumulative-buffer nil + "Non-nil for Rdebug secondary buffers that grow.") + +;; This is used to ensure that the original frame configuration is +;; restored even when the user re-starts the debugger several times. +(defvar rdebug-window-configuration-state 'original + "Represent the window layout that currently is in use. +Can be `original' or `debugger'.") + +;; FIXME instead of just a list of commands it should a list of pairs +;; command and lambda callback routine to call with the shell output. +(defvar rdebug-call-queue '() + "List of commands queued up for results of a `rdebug-call'. + +Each entry is a list of the following form: + + (name ... options ...) + +Name is the actual command string. Options are zero or more tags +describing what should happen with the output. + +This is buffer local variable to the rdebug shell buffer.") + +;; TODO: Make this buffer-local to the shell buffer. +(defvar rdebug-inferior-status nil + "The status of the Ruby program debugged under RDebug.") + +;; Unlike the gdb implementation, we don't have to actively update the +;; mode line. +(defvar rdebug-mode-line-process + '(:eval + (and (fboundp 'rdebug-display-inferior-status) + (rdebug-display-inferior-status))) + "A string representing the current debugger state, or nil. +The mode line is displayed in all source and secondary buffers.") +;; Needed to get :eval to work. +(put 'rdebug-mode-line-process 'risky-local-variable t) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-vars) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-vars.el ends here diff --git a/emacs/.svn/text-base/rdebug-watch.el.svn-base b/emacs/.svn/text-base/rdebug-watch.el.svn-base new file mode 100644 index 0000000..b5a6e9b --- /dev/null +++ b/emacs/.svn/text-base/rdebug-watch.el.svn-base @@ -0,0 +1,132 @@ +;;; rdebug-watch.el --- This file contains code dealing with the Ruby +;;; debugger's watch (AKA display) secondary buffer. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id$ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: +;; See the manual and the file `rdebug.el' for more information. + +;;; Code: + +(require 'rdebug-dbg) + +(defvar rdebug-watch-mode-map + (let ((map (make-sparse-keymap))) + (suppress-keymap map) + (define-key map "a" 'rdebug-watch-add) + (define-key map "\C-d" 'rdebug-watch-delete) + (define-key map "d" 'rdebug-watch-delete) + (define-key map "e" 'rdebug-watch-edit) + (define-key map "\r" 'rdebug-watch-edit) + (rdebug-populate-digit-keys map) + (rdebug-populate-secondary-buffer-map map) + + ;; -------------------- + ;; The "Watch window" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key-after map [menu-bar debugger watch] + (cons "Watch window" submenu) + 'placeholder)) + + (define-key map [menu-bar debugger watch delete] + '(menu-item "Delete" rdebug-watch-delete + :enable (eq major-mode 'rdebug-watch-mode))) + (define-key map [menu-bar debugger watch goto] + '(menu-item "Edit" rdebug-watch-edit + :enable (eq major-mode 'rdebug-watch-mode))) + (define-key map [menu-bar debugger watch add] + '(menu-item "Add" rdebug-watch-add)) + + map) + "Keymap used in the watch buffer in the `rdebug' Ruby debugger.") + +(defun rdebug-display-watch-buffer () + "Display the rdebug watch buffer." + (interactive) + (rdebug-display-secondary-buffer "watch")) + +(defun rdebug-watch-mode () + "Major mode for displaying watched expressions in the `rdebug' Ruby debugger. + +\\{rdebug-watch-mode}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-watch-mode) + (setq mode-name "RDEBUG Watch") + (setq buffer-read-only t) + (setq truncate-lines t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (set (make-local-variable 'font-lock-defaults) + '(rdebug-variables-font-lock-keywords)) + (use-local-map rdebug-watch-mode-map) + (run-mode-hooks 'rdebug-watch-mode-hook)) + +(defun rdebug-setup-watch-buffer (buf comint-buffer) + "Set up the rdebug debugger watch secondary buffer. + +This buffer contains display expressions. BUF is the buffer to set up and COMINT-BUFFER be the assocated gud process buffer." + (rdebug-debug-enter "rdebug-setup-watch-buffer" + (with-current-buffer buf + (rdebug-watch-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer)))) + +(defun rdebug-watch-add (expr) + "Add EXPR to watch in the `rdebug' Ruby debugger." + (interactive "sRuby expression: ") + (if (not (string= expr "")) + (gud-call (format "display %s" expr)))) + + +(defun rdebug-watch-delete () + "Delete a display expression in the `rdebug' Ruby debugger." + (interactive) + (save-excursion + (beginning-of-line) + (if (looking-at "^\\([0-9]+\\):") + (gud-call (format "undisplay %s" (match-string 1)))))) + +(defun rdebug-watch-edit (number expr) + "Edit a display expression in the `rdebug' Ruby debugger. +Argument NUMBER is the display expression number. +Argument EXPR is the expression for display number NUMBER." + (interactive + (let ((number nil) + (expr nil)) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\([0-9]+\\): *\\([^=]*[^= ]\\) *=") + (setq number (match-string 1)) + (setq expr (match-string 2)) + (setq expr (read-from-minibuffer "Ruby expression: " expr))) + (list number expr)))) + (when expr + (gud-call (format "undisplay %s" number)) + (gud-call (format "display %s" expr)))) + + +(provide 'rdebug-watch) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-watch.el ends here diff --git a/emacs/.svn/text-base/rdebug.el.svn-base b/emacs/.svn/text-base/rdebug.el.svn-base new file mode 100644 index 0000000..2a326a1 --- /dev/null +++ b/emacs/.svn/text-base/rdebug.el.svn-base @@ -0,0 +1,326 @@ +;;; rdebug.el --- Ruby debugger user interface, startup file. + +;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id: rdebug.el 409 2007-12-14 02:36:37Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; +;; Introduction: +;; +;; This is a full-blown debugger user interface to the Ruby rdebug +;; debugger shell. +;; +;; The main features are: +;; +;; * Window layout with dedicated windows for: +;; + Local and member variables +;; + Stack trace +;; + Display expressions +;; + Breakpoints +;; + Output +;; + Debugger Shell +;; +;; * Source-level debugging: +;; + The current source file is shown and current line is marked. +;; + Function keys bindings for effective stepping in the source code. +;; + A "Debugger" menu for easy access to all features. +;; +;; * A number of predefined window layouts and key bindings are +;; supplied, including binding that emulate Eclipse and NetBeans. +;; The user can easily provide their own window layout and +;; settings. +;; +;; The default window layout looks like the following: +;; +;; +----------------------------------------------------------------------+ +;; | Toolbar | +;; +-----------------------------------+----------------------------------+ +;; | Debugger shell | Variables buffer | +;; +-----------------------------------+----------------------------------+ +;; | | | +;; | Source buffer | Output buffer | +;; | | | +;; +-----------------------------------+----------------------------------+ +;; | Stack buffer | Breakpoints buffer | +;; +-----------------------------------+----------------------------------+ +;; + +;; +;; Installation: +;; +;; To use this package, place the following line in an appropriate +;; init file (for example ~/.emacs): +;; +;; (require 'rdebug) +;; + +;; +;; History and Future: +;; +;; The design of this debugger user interface was inspired by +;; `gdb-ui', a similar user interface to GDB. +;; +;; Hopefully, rdebug, gdb-ui, and other emacs user interfaces could +;; join forces to create a common user-level look and feel, and a +;; battery of underlying support functions. +;; + +;; +;; This file contains only user-customizable variables and code to +;; load the other files when needed. +;; + +;;; Code: + +;; ------------------------------------------------------------------- +;; Consistency checks. +;; + +(if (< emacs-major-version 22) + (error + "This version of rdebug.el needs at least Emacs 22 or greater - you have version %d." + emacs-major-version)) + + +;; ------------------------------------------------------------------- +;; Support functions. +;; + +(defun rdebug-directory () + "The directory of this file, or nil." + (let ((file-name (or load-file-name + (symbol-file 'rdebug-directory)))) + (if file-name + (file-name-directory file-name) + nil))) + + +(defun rdebug-compare-filenames (f1 f2) + "Canonicalize and compare file names." + ;; Canonicalize by: + ;; 1) file-truename ensures that the file has got the correct case, + ;; and that "..":s in the path are eliminated. + ;; 2) file-name-as-directory ensures "/foo" and "/foo/" becomes equal. + + ;; Note: for some reason, when the `comp-elisp' external program is + ;; used, `nil' is part of `load-path'. + (if f1 + (setq f1 (file-name-as-directory (file-truename f1)))) + (if f2 + (setq f2 (file-name-as-directory (file-truename f2)))) + (equal f1 f2)) + + +;; Add the directory of `rdebug.el' to the load-path. This ensures +;; that all the user have do to use this package is to load this file. +(let ((dir (rdebug-directory))) + (if dir + (add-to-list 'load-path dir nil 'rdebug-compare-filenames))) + + +;; ------------------------------------------------------------------- +;; Autoloads. +;; + +(autoload 'rdebug "rdebug-core" + "Run the rdebug Ruby debugger and start the Emacs user interface. + +By default, the \"standard\" user window layout looks like the following: + ++----------------------------------------------------------------------+ +| Toolbar | ++-----------------------------------+----------------------------------+ +| Debugger shell | Variables buffer | ++-----------------------------------+----------------------------------+ +| | | +| Source buffer | Output buffer | +| | | ++-----------------------------------+----------------------------------+ +| Stack buffer | Breakpoints buffer | ++-----------------------------------+----------------------------------+ + +The variable `rdebug-many-windows-layout-function' can be +customized so that another layout is used. In addition to a +number of predefined layouts it's possible to define a function +to perform a custom layout. + +If `rdebug-many-windows' is nil, only a traditional debugger +shell and source window is opened. + +The directory containing the debugged script becomes the initial +working directory and source-file directory for your debugger. + +The custom variable `gud-rdebug-command-name' sets the command +and options used to invoke rdebug." t) + + +(autoload 'rdebug-turn-on-debugger-support "rdebug-source" + "Enable extra source buffer support for the `rdebug' Ruby debugger. + +This includes a 'Debugger' menu and special key bindings when the +debugger is active." + t) + + +(autoload 'rdebug-track-attach "rdebug-track" + "Do things to make the current process buffer work like a +rdebug command buffer." t) + +(autoload 'turn-on-rdebug-track-mode "rdebug-track" + "Turn on rdebugtrack mode. + +This function is designed to be added to hooks, for example: + (add-hook 'comint-mode-hook 'turn-on-rdebugtrack-mode)" + t) + + +(add-hook 'ruby-mode-hook 'rdebug-turn-on-debugger-support) + +;; This is needed, or at least the docstring part of it is needed to +;; get the customization menu to work in Emacs 23. +(defgroup rdebug nil + "The Ruby debugger" + :group 'processes + :group 'tools) + +;; ------------------------------------------------------------------- +;; User definable variables +;; + +(defcustom gud-rdebug-command-name + "rdebug --emacs 3" + "File name for executing the Ruby debugger and command options. +This should be an executable on your path, or an absolute file name." + :type 'string + :group 'gud) + +(defcustom rdebug-line-width 120 + "Length of line before truncation occurs. +This value limits output in secondary buffers." + :type 'integer + :group 'rdebug) + +(defcustom rdebug-many-windows t + "*If non-nil, use the full debugger user interface, see `rdebug'. + +However only set to the multi-window display if the rdebug +command invocation has an annotate options (\"--annotate 3\")." + :type 'boolean + :group 'rdebug) + +(defcustom rdebug-use-separate-io-buffer t + "*If non-nil, output goes to a dedicated windows. + +This only applies when `rdebug-many-windows' is non-nil." + :type 'boolean + :group 'rdebug) + +(defcustom rdebug-populate-common-keys-function + 'rdebug-populate-common-keys-standard + "The function to call to populate key bindings common to all rdebug windows. +This includes the secondary windows, the debugger shell, and all +Ruby source buffers when the debugger is active. + +This variable can be bound to the following: + +* nil -- Don't bind any keys. + +* `rdebug-populate-common-keys-standard' -- Bind according to a widely used + debugger convention: + +\\{rdebug-example-map-standard} + +* `rdebug-populate-common-keys-eclipse' -- Bind according to Eclipse. + +\\{rdebug-example-map-eclipse} + +* `rdebug-populate-common-keys-netbeans' -- Bind according to NetBeans. + +\\{rdebug-example-map-netbeans} + +* Any other value is expected to be a callable function that takes one + argument, the keymap, and populates it with suitable keys." + :type 'function + :group 'rdebug) + +(defcustom rdebug-restore-original-window-configuration :many + "*Control if the original window layout is restored when the debugger exits. +The value can be t, nil, or :many. + +A value of t means that the original layout is always restored, +nil means that it's never restored. + +:many means that the original layout is restored only when +`rdebug-many-windows' is used." + :type '(choice (const :tag "Always restore" t) + (const :tag "Never restore" nil) + (const :tag "Restore in many windows mode" :many)) + :group 'rdebug) + +(defcustom rdebug-use-separate-io-buffer t + "Non-nil means display output from the debugged program in a separate buffer." + :type 'boolean + :group 'gud) + + +(defcustom rdebug-window-layout-function + 'rdebug-window-layout-standard + "*A function that performs the window layout of `rdebug'. + +This is only used in `rdebug-many-windows' mode. This should be +bound to a function that performs the actual window layout. The +function should takes two arguments, the first is the source +buffer and the second the name of the script to debug. + +Rdebug provides the following predefined layout functions: + +* `rdebug-window-layout-standard' -- See `rdebug' + +* `rdebug-window-layout-no-shell' -- Standard + Display, no Shell + +* `rdebug-window-layout-conservative' -- Source + Shell + Output + +* `rdebug-window-layout-stack-of-windows' -- Extra windows to the right + +* `rdebug-window-layout-rocky' -- Rocky's own layout" + :type + '(choice + (function :tag "Standard" rdebug-window-layout-standard) + (function :tag "Conservative" rdebug-window-layout-conservative) + (function :tag "Stack of windows" rdebug-window-layout-stack-of-windows) + (function :tag "Rocky's own" rdebug-window-layout-rocky) + (function :tag "Rocky's II" rdebug-window-layout-rocky2) + (function :tag "Other" function)) + :group 'rdebug) + +(defcustom rdebug-source-location-ring-size 150 + "Size of rdebug position history ring." + :type 'integer + :group 'rdebug) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug) + +;;; rdebug.el ends here diff --git a/emacs/Makefile.am b/emacs/Makefile.am new file mode 100644 index 0000000..2bbc81e --- /dev/null +++ b/emacs/Makefile.am @@ -0,0 +1,130 @@ +# Copyright (C) 2007, 2008 Rocky Bernstein rocky@gnu.org +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with Bash; see the file COPYING. If not, write to the Free Software +# Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. +#$Id: Makefile.am,v 1.10 2007/04/13 00:59:33 rockyb Exp $ + +lisp_files = rdebug.el \ + rdebug-annotate.el \ + rdebug-breaks.el \ + rdebug-cmd.el \ + rdebug-core.el \ + rdebug-dbg.el \ + rdebug-error.el \ + rdebug-fns.el \ + rdebug-frames.el \ + rdebug-gud.el \ + rdebug-help.el \ + rdebug-info.el \ + rdebug-layouts.el \ + rdebug-locring.el \ + rdebug-output.el \ + rdebug-regexp.el \ + rdebug-secondary.el\ + rdebug-shortkey.el \ + rdebug-source.el \ + rdebug-track.el \ + rdebug-varbuf.el \ + rdebug-vars.el \ + rdebug-watch.el +check_DATA = test/elk-test.el \ + test/test-annotate.el \ + test/test-cmd.el \ + test/test-core.el \ + test/test-fns.el \ + test/test-gud.el \ + test/test-indent.el \ + test/test-regexp.el \ + test/test-shortkey.el + +EXTRA_DIST = $(lisp_files) $(check_DATA) +ELCFILES = rdebug.elc \ + rdebug-annotate.elc \ + rdebug-breaks.elc \ + rdebug-cmd.elc \ + rdebug-core.elc \ + rdebug-dbg.elc \ + rdebug-error.elc \ + rdebug-fns.elc \ + rdebug-gud.elc \ + rdebug-frames.elc \ + rdebug-help.elc \ + rdebug-info.elc \ + rdebug-layouts.elc \ + rdebug-locring.elc \ + rdebug-output.elc \ + rdebug-regexp.elc \ + rdebug-secondary.elc \ + rdebug-shortkey.elc \ + rdebug-source.elc \ + rdebug-track.elc \ + rdebug-varbuf.elc \ + rdebug-vars.elc \ + rdebug-watch.elc +if INSTALL_EMACS_LISP +lisp_LISP = $(lisp_files) +CHECK_FILES = \ + check-annotate \ + check-cmd \ + check-core \ + check-fns \ + check-frames \ + check-gud \ + check-indent \ + check-regexp \ + check-shortkey + +check: $(CHECK_FILES) + +check-annotate: rdebug-annotate.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-annotate.el ) + +check-cmd: rdebug-gud.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-cmd.el ) + +check-core: rdebug-core.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-core.el ) + +check-fns: rdebug-fns.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-fns.el ) + +check-frames: rdebug-frames.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-frames.el ) + +check-gud: rdebug-gud.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-gud.el ) + +check-indent: $(lisp_files) + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-indent.el ) + +check-regexp: rdebug-regexp.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-regexp.el ) + +check-shortkey: rdebug-shortkey.el + (cd $(srcdir)/test && \ + $(EMACS) -batch -q -l test-shortkey.el ) +endif + +PHONY = $(CHECK_FILES) + +test: check + diff --git a/emacs/rdebug-annotate.el b/emacs/rdebug-annotate.el new file mode 100644 index 0000000..04a3905 --- /dev/null +++ b/emacs/rdebug-annotate.el @@ -0,0 +1,385 @@ +;;; rdebug-annotate.el --- Ruby debugger output filtering - which +;;; includes annotation handling. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-annotate.el 786 2008-04-02 00:50:27Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file contains code dealing with filter of debugger output a large +;; part of which may contain annotations. + +;;; Code: + +(require 'gud) +(require 'gdb-ui) +(require 'rdebug-dbg) +(require 'rdebug-error) +(require 'rdebug-fns) +(require 'rdebug-info) +(require 'rdebug-layouts) +(require 'rdebug-locring) +(require 'rdebug-regexp) +(require 'rdebug-shortkey) +(require 'rdebug-source) +(require 'rdebug-vars) + +(defvar rdebug-non-annotated-text-kind nil + "Represent what non-annotated text is. + +This can be: + * nil -- plain shell output + * :output -- output from the command being debugged + * :info -- text for the \"info\" secondary window. + * :message -- message the text to the echo area. + * :cmd -- a command + result, which might go into the \"info\" window. + +See the function `rdebug-cmd-process' for details on :cmd.") + +(defvar rdebug-annotation-setup-map + (progn + (define-hash-table-test 'str-hash 'string= 'sxhash) + (let ((map (make-hash-table :test 'str-hash))) + (puthash "breakpoints" 'rdebug-setup-breakpoints-buffer map) + ;;(puthash "error" 'rdebug-setup-error-buffer map) + (puthash "frame" 'rdebug-setup-frame-buffer map) + (puthash "variables" 'rdebug-setup-variables-buffer map) + (puthash "watch" 'rdebug-setup-watch-buffer map) + (puthash "output" 'rdebug-setup-output-buffer map) + (puthash "info" 'rdebug-setup-info-buffer map) + (puthash "help" 'rdebug-setup-secondary-window-help-buffer map) + map))) + +(defun rdebug-temp-show (text) + "Arrange to show string as in sort of temporary way. Perhaps like a tooltip" + (tooltip-show text)) + +(defun rdebug-marker-filter-next-item (string) + "The next item for the rdebug marker filter to process. + +Return (item . rest) or nil." + (rdebug-debug-message "ACC: %S" string) + (cond + ;; Empty line, we're done. + ((equal (length string) 0) + nil) + ;; A single ^Z, this could become a new annotation, so lets stop here. + ((string= string "\032") + nil) + ;; A half-baked annotation, lets stop here. + ((and (string-match "^\032\032" string) + (not (string-match "\n" string))) + nil) + (t + (let ((split-point + (cond ((string-match "\032\032" string) + (let ((beg (match-beginning 0))) + (if (equal beg 0) + (if (string-match "^\032\032" string 2) + (match-beginning 0) + (length string)) + beg))) + ((eq (elt string (- (length string) 1)) ?\32) + -1) + (t + (length string))))) + (cons (substring string 0 split-point) (substring string split-point)))))) + +;; There's no guarantee that Emacs will hand the filter the entire +;; marker at once; it could be broken up across several strings. We +;; might even receive a big chunk with several markers in it. If we +;; receive a chunk of text which looks like it might contain the +;; beginning of a marker, we save it here between calls to the +;; filter. +(defun gud-rdebug-marker-filter (string) + "Filter function for process output of the rdebug Ruby debugger." + (rdebug-debug-enter "gud-rdebug-marker-filter:" + (rdebug-debug-message "GOT: %S" string) + (if rdebug-non-annotated-text-kind + (rdebug-debug-message " Text is %S" rdebug-non-annotated-text-kind)) + (setq gud-marker-acc (concat gud-marker-acc string)) + (rdebug-debug-message "TOT: %S" gud-marker-acc) + (let ((shell-output "") ; Output to debugger shell window. + (done nil) + item) + ;; The following loop peels of one "item" at a time. An item is + ;; a un-annotated section or an annotation. (This is taken care + ;; of by the `rdebug-marker-filter-next-item' function.) + ;; + ;; An Annotation can be a one-liner (where anything following + ;; the annotation is treated as un-annotated text) or a full + ;; annotation (which stretches to the next annotation). + ;; + ;; The concept of one-liners (no phun intended) is to allow + ;; continuous output, a "starting" annotation simply sets up the + ;; environment for sending lines to the output window, any text + ;; following it right now, or in later chunks of data, is + ;; redirected to the output window. + (while (and (not done) + (let ((pair (rdebug-marker-filter-next-item gud-marker-acc))) + (rdebug-debug-message "Next item: %S" pair) + (and pair + (progn + (setq item (car pair)) + (setq gud-marker-acc (cdr pair)) + t)))) + ;; Note: Regexp:s are greedy, i.e. the char parts wins over + ;; the .* part. + (if (not (string-match "^\032\032\\([-a-z]*\\).*\n" item)) + ;; Non-annotated text (or the content of one-liners) goes + ;; straight into the debugger shell window, or to the + ;; output window. + (cond ((and (eq rdebug-non-annotated-text-kind :output) + rdebug-use-separate-io-buffer) + (rdebug-process-annotation "starting" item)) + ((eq rdebug-non-annotated-text-kind :info) + (rdebug-process-annotation "info" item)) + (t + (if (eq rdebug-non-annotated-text-kind :cmd) + (rdebug-cmd-process item)) + (setq shell-output (concat shell-output item)))) + ;; Handle annotation. + (let* ((line-end (match-end 0)) + (name (match-string 1 item)) + ;; "prompt" is needed to handle "quit" in the shell correctly. + (one-liner + (member name + '("" "exited" "source" "prompt" "starting"))) + (next-annotation (string-match "\032\032" + gud-marker-acc))) + ;; For one-liners, shuffle some text back to the accumulator. + (when one-liner + (setq gud-marker-acc (concat (substring item line-end) + gud-marker-acc)) + (setq item (substring item 0 line-end))) + (if (or next-annotation + one-liner) + ;; ok, annotation complete, process it and remove it + (let* ((contents (substring item line-end)) + (old-kind rdebug-non-annotated-text-kind)) + (rdebug-debug-message "Name: %S Content: %S Kind: %S" + name contents + rdebug-non-annotated-text-kind) + + ;; This is a global state flag, this allows us to + ;; redirect any further text to the output buffer. + (set + (make-local-variable 'rdebug-non-annotated-text-kind) + (cond ((string= name "starting") + :output) + ((string= name "prompt") + (rdebug-cmd-clear) + :cmd) + ((string= name "exited") + ;; Create a fake command whose output we + ;; handle in the cmd system. (We might not + ;; receive all of the message at once, we we + ;; need some kind of accumukator, which the + ;; cmd system provides.) + (setq rdebug-inferior-status "exited") + (rdebug-cmd-clear) + (setq rdebug-call-queue + (cons '("***exited***" :message) + rdebug-call-queue)) + :cmd) + (t nil))) + + (when (and (eq old-kind :cmd) + (not (eq rdebug-non-annotated-text-kind :cmd))) + (rdebug-debug-message + "New kind: %S" rdebug-non-annotated-text-kind) + (rdebug-cmd-done)) + + ;; Process the annotation. + (cond ((string= name "starting") + (setq rdebug-inferior-status "running")) + ((string= name "stopped") + (setq rdebug-inferior-status "stopped")) + ((string= name "exited") + (setq rdebug-inferior-status "exited")) + ((string= name "pre-prompt") + ;; Strip of the trailing \n (this is probably + ;; a bug in processor.rb). + (if (string= (substring contents -1) "\n") + (setq contents (substring contents 0 -1))) + (if (string-match "post-mortem" contents) + (setq rdebug-inferior-status "crashed")) + (setq shell-output (concat shell-output contents))) + ((string= name "source") + (if (string-match gud-rdebug-marker-regexp item) + ;; Extract the frame position from the marker. + (setq gud-last-frame + (cons (match-string 1 item) + (string-to-number + (match-string 2 item)))))) + (t (rdebug-process-annotation name contents)))) + ;; This is not a one-liner, and we haven't seen the next + ;; annotation, so we have to treat this as a partial + ;; annotation. Save it and hope that the we can process + ;; it the next time we're called. + (setq gud-marker-acc (concat item gud-marker-acc)) + (setq done t))))) + + (when gud-last-frame + ;; Display the source file where we want it, gud will only pick + ;; an arbitrary window. + (rdebug-pick-source-window) + (rdebug-set-frame-arrow (gud-find-file (car gud-last-frame))) + (if (equal 0 rdebug-frames-current-frame-number) + (rdebug-locring-add gud-last-frame + rdebug-source-location-ring))) + (rdebug-short-key-mode-maybe-activate) + + (unless (string= shell-output "") + (rdebug-debug-message "Output: %S" shell-output)) + (rdebug-debug-message "REM: %S" gud-marker-acc) + + shell-output))) + +(defun rdebug-process-annotation (name contents) + "Called after `gud-rdebug-marker-filter' found a complete +`name' annotation with string `contents'. Send it to the right +place for processing." + (rdebug-debug-enter (format "rdebug-process-annotation %s" name) + ;; Ruby-debug uses the name "starting" for process output (just like + ;; GDB). However, it's better to present the buffer as "output" to + ;; the user. Ditto for "display" and "watch". + (cond ((string= name "starting") + (setq name "output")) + ((string= name "display") + (setq name "watch")) + ((string= name "stack") + (setq name "frame")) + ((string= name "error-begin") + (setq name "error"))) + ;; New "info" + (if (string= name "exited") + (setq name "info")) + (if (string= name "error") + (rdebug-errmsg contents)) + (let ((setup-func (gethash name rdebug-annotation-setup-map))) + (when setup-func + (let ((buf (rdebug-get-buffer name gud-target-name)) + ;; Buffer local, doesn't survive the buffer change. + (comint-buffer gud-comint-buffer)) + (with-current-buffer buf + (setq buffer-read-only t) + (let ((inhibit-read-only t)) + (set (make-local-variable 'rdebug-current-line-number) + (line-number-at-pos)) + (set (make-local-variable 'gud-last-frame) gud-last-frame) + (if rdebug-accumulative-buffer + (goto-char (point-max)) + (erase-buffer)) + (insert contents) + (funcall setup-func buf comint-buffer)))))) + (cond ((and (string= name "info") + (not (string= contents ""))) + (save-selected-window + (rdebug-display-info-buffer)))))) + + +;; ------------------------------------------------------------ +;; Mode line displayer. +;; + +;; The variable rdebug-mode-line-process uses this to generate the +;; actual string to display. +(defun rdebug-display-inferior-status () + "Return a (propertized) string, or nil, to be displayed in the mode line." + (if (and gud-comint-buffer + (buffer-name gud-comint-buffer) + (get-buffer-process gud-comint-buffer) + rdebug-inferior-status) + (let ((s rdebug-inferior-status)) + (cond ((string= rdebug-inferior-status "running") + (setq s (propertize s 'face font-lock-type-face))) + (t + (setq s (propertize s 'face font-lock-warning-face)))) + (concat ":" s)) + ;; No process, don't display anything. + nil)) + +;; ------------------------------------------------------------ +;; Command output parser. +;; + +(defvar rdebug-cmd-acc "" + "The accumulated output of the current command. + +Note, on some systems the external process echoes the command, +which is included in the output.") + +;; Called when a new command starts. +(defun rdebug-cmd-clear () + "Called when the Rdebug filter find the start of a new commands." + (rdebug-debug-enter "rdebug-cmd-clear" + (setq rdebug-cmd-acc ""))) + +;; Called with command output, this can be called any number of times. +(defun rdebug-cmd-process (s) + "Called when the Rdebug filter find the command output. +This may be called any number of times." + (rdebug-debug-enter (format "rdebug-cmd-process %S" s) + (setq rdebug-cmd-acc (concat rdebug-cmd-acc s)))) + +;; Called when command has finished. +(defun rdebug-cmd-done () + "Called when the Rdebug filter find the end of a commands." + (rdebug-debug-enter "rdebug-cmd-done" + ;; car-safe is used since rdebug-call-queue can be empty. + (let ((entry (car-safe rdebug-call-queue)) + (text rdebug-cmd-acc)) + (when entry + (rdebug-debug-message "Entry: %S Acc:%S" rdebug-call-queue rdebug-cmd-acc) + (setq rdebug-call-queue (cdr rdebug-call-queue)) + (let ((saved-cmd (car entry)) + (options (cdr entry))) + ;; In cast the external process echoed the actual command, + ;; remove it. + (when (and (>= (length text) + (length saved-cmd)) + (string= saved-cmd (substring text 0 (length saved-cmd)))) + (setq text (substring text (+ 1 (length saved-cmd))))) + (rdebug-debug-message "Text: %S" text) + ;; Optionally display the result. + (if (memq :tooltip options) + (rdebug-temp-show text)) + (if (memq :info options) + (rdebug-process-annotation "info" text)) + (when (memq :message options) + ;; Remove trailing newlines (chomp). + (while (and (> (length text) 0) + (eq (elt text (- (length text) 1)) ?\n)) + (setq text (substring text 0 -1))) + (message text))))))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-annotate) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-annotate.el ends here diff --git a/emacs/rdebug-breaks.el b/emacs/rdebug-breaks.el new file mode 100644 index 0000000..5346fd1 --- /dev/null +++ b/emacs/rdebug-breaks.el @@ -0,0 +1,407 @@ +;;; rdebug-breaks.el --- This file contains code dealing with the Ruby +;;; debugger's breakpoints and the breakpoint secondary buffer. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-breaks.el 780 2008-03-21 19:04:12Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file contains code dealing with the breakpoints and the +;; breakpoints secondary buffer. + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-gud) +(require 'rdebug-regexp) +(require 'rdebug-secondary) +(require 'rdebug-source) +(require 'rdebug-vars) + +(defun rdebug-display-breakpoints-buffer () + "Display the rdebug breakpoints buffer." + (interactive) + (rdebug-display-secondary-buffer "breakpoints")) + +(defvar rdebug-breakpoint-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [double-mouse-1] 'rdebug-goto-breakpoint-mouse) + (define-key map [mouse-2] 'rdebug-goto-breakpoint-mouse) + (define-key map [mouse-3] 'rdebug-goto-breakpoint-mouse) + (define-key map "t" 'rdebug-toggle-breakpoint) + (define-key map "i" 'rdebug-add-breakpoint-condition) + (define-key map [insert] 'rdebug-add-breakpoint-condition) + (rdebug-populate-digit-keys map) + (define-key map [(control m)] 'rdebug-goto-breakpoint) + (define-key map [?d] 'rdebug-delete-breakpoint) + (rdebug-populate-secondary-buffer-map map) + + ;; -------------------- + ;; The "Breakpoints window" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key-after map [menu-bar debugger breakpoints] + (cons "Breakpoints window" submenu) + 'placeholder)) + + (define-key map [menu-bar debugger breakpoints toggle] + '(menu-item "Toggle breakpoint" rdebug-toggle-breakpoint)) + + (define-key map [menu-bar debugger breakpoints goto] + '(menu-item "Goto breakpoint" rdebug-goto-breakpoint)) + + (define-key map [menu-bar debugger breakpoints delete] + '(menu-item "Delete breakpoint" rdebug-delete-breakpoint)) + + map) + "Keymap to navigate/set/enable rdebug breakpoints.") + +;; Here the "anchored match" method is used, see `font-lock-keywords' +;; for details. +(defvar rdebug-breakpoint-font-lock-keywords + '(("\\([0-9]+\\) +\\(\\(n\\)\\|\\(y\\)\\) +at " + (1 font-lock-constant-face) + (3 font-lock-type-face nil t) ; t = ok if not present + (4 font-lock-warning-face nil t) ; ditto. + ;; File name and line + ("\\(.*\\):\\([0-9]+\\)$" + nil ; Preform (not used) + nil ; Postfrom (not used) + (1 font-lock-warning-face) + (2 font-lock-constant-face)) + ;; Class:function + ("\\(.*\\):\\([a-zA-Z_].+\\)$" + nil ; Preform (not used) + nil ; Postfrom (not used) + (1 font-lock-type-face) + (2 font-lock-function-name-face)))) + "Rules for coloring the rdebug breakpoints buffer.") + +(defun rdebug-breakpoint-mode () + "Major mode for displaying breakpoints in the `rdebug' Ruby debugger. + +\\{rdebug-breakpoint-mode-map}" + (kill-all-local-variables) + (setq major-mode 'rdebug-breakpoint-mode) + (setq mode-name "RDEBUG Breakpoints") + (use-local-map rdebug-breakpoint-mode-map) + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (set (make-local-variable 'font-lock-defaults) + '(rdebug-breakpoint-font-lock-keywords)) + (run-mode-hooks 'rdebug-breakpoint-mode-hook)) + + +(defun rdebug-setup-breakpoints-buffer (buf comint-buffer) + "Detect breakpoint lines and set up keymap and mouse navigation. +Argument BUF is the buffer to set up. +Argument COMINT-BUFFER is the assocaited gud process buffer." + (rdebug-debug-enter "rdebug-setup-breakpoints-buffer" + (with-current-buffer buf + (let ((inhibit-read-only t) + (old-line-number (buffer-local-value 'rdebug-current-line-number + buf))) + (rdebug-breakpoint-mode) + (goto-char (point-min)) + (while (not (eobp)) + (let ((b (line-beginning-position)) (e (line-end-position))) + (when (string-match rdebug-breakpoint-regexp + (buffer-substring b e)) + (add-text-properties b e + (list 'mouse-face 'highlight + 'keymap rdebug-breakpoint-mode-map))) + (forward-line))) + (goto-line old-line-number))) + (rdebug-breakpoint-parse-and-update-cache) + (rdebug-breakpoint-update-icons (rdebug-breakpoint-all)))) + + +(defvar rdebug-breakpoint-cache '() + "The cached return value of `rdebug-breakpoint-all'. + +Buffer-local to the debugger shell window.") + + +;; Implementation note: If Emacs could talk directly to the Ruby +;; debugger, this would be roughly "Debugger.breakpoints". Since we +;; currently can't do that we parse the content of the breakpoints +;; window. +;; +;; Note: The :function kind is not yet implemented. +(defun rdebug-breakpoint-parse-and-update-cache () + "Build up the return value of `rdebug-breakpoint-all'." + (save-excursion + (goto-char (point-min)) + (let ((res '())) + (while (not (eobp)) + (when (looking-at rdebug-breakpoint-regexp) + (push (list :file + ;; Break point number + (string-to-number (match-string 1)) + ;; Enabled + (string= (match-string 2) "y") + ;; File name + (file-truename + (match-string-no-properties 3)) + ;; Line number + (string-to-number (match-string 4))) + res)) + (forward-line 1)) + ;; The result goes into a buffer-local variable in the debugger + ;; shell. (This ensures that this would work in a multi-session + ;; environment.) + (if gud-comint-buffer + (with-current-buffer gud-comint-buffer + (set (make-local-variable 'rdebug-breakpoint-cache) + (nreverse res))))))) + + +(defun rdebug-breakpoint-all () + "Return a list of all breakpoints. + +Each entry in the list is on the form: + + (:file number enabled file line) + +or + + (:function number enabled class function)" + (and gud-comint-buffer + (buffer-local-value 'rdebug-breakpoint-cache gud-comint-buffer))) + + +(defun rdebug-file-and-line-arg () + "Return the current file and line number as a list." + (save-excursion + (beginning-of-line) + (list (buffer-file-name) (+ 1 (count-lines (point-min) (point)))))) + +(defun rdebug-breakpoint-on-line (file line) + "Return a list of the breakpoints on the file FILE and current source LINE." + (let ((res '())) + (dolist (entry (rdebug-breakpoint-all)) + (if (and (eq (nth 0 entry) :file) + (string= (nth 3 entry) file) + (equal (nth 4 entry) line)) + (push entry res))) + res)) + + +(defun rdebug-toggle-source-breakpoint (file line) + "Toggle break point in FILE on current source LINE." + (interactive (rdebug-file-and-line-arg)) + (cond ((eq major-mode 'rdebug-breakpoint-mode) + (rdebug-delete-breakpoint)) + ((null file) + ;; Do nothing. + ) + (t + (let ((bps (rdebug-breakpoint-on-line file line))) + (if bps + (gud-call (format "delete %s" (nth 1 (car bps)))) + (gud-call (format "break %s:%d" file line))))))) + + +(defun rdebug-toggle-source-breakpoint-enabled (file line) + "Enable or disable a breakpoint in FILE on the current source LINE." + (interactive (rdebug-file-and-line-arg)) + (cond ((eq major-mode 'rdebug-breakpoint-mode) + (rdebug-toggle-breakpoint)) + ((null file) + ;; Do nothing. + ) + (t + (let ((bps (rdebug-breakpoint-on-line file line))) + (if bps + ;; Note: If the line contains more than one simply use the + ;; first one. + (let ((entry (car bps))) + (if (nth 2 entry) + (gud-call (format "disable %s" (nth 1 entry))) + (gud-call (format "enable %s" (nth 1 entry))))) + (gud-call (format "break %s:%d" file line))))))) + + +;; --------------------------------------------------------- +;; Commands of the rdebug breakpoints buffer. +;; + +(defun rdebug-delete-breakpoint (&optional pt) + "Deletes the breakpoint at PT in the breakpoints buffer." + (interactive "d") + (save-excursion + (if pt + (goto-char pt)) + (let ((s (buffer-substring (line-beginning-position) (line-end-position)))) + (when (string-match rdebug-breakpoint-regexp s) + (let ((bpnum (substring s (match-beginning 1) (match-end 1)))) + (gud-call (format "delete %s" bpnum))))))) + +(defun rdebug-goto-breakpoint (pt) + "Displays the location in a source file of the selected breakpoint. +Argument PT indicates the file and line where the breakpoint should be set." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (buffer-substring (line-beginning-position) (line-end-position)))) + (when (string-match rdebug-breakpoint-regexp s) + (rdebug-display-line + (substring s (match-beginning 3) (match-end 3)) + (string-to-number (substring s (match-beginning 4) (match-end 4)))) + )))) + + +(defun rdebug-goto-breakpoint-mouse (event) + "Displays the location in a source file of the selected breakpoint." + (interactive "e") + (with-current-buffer (window-buffer (posn-window (event-end event))) + (rdebug-goto-breakpoint (posn-point (event-end event))))) + + +(defun rdebug-get-breakpoint-number (pt) + "Return the current breakpoint number in the breakpoint secondary window or nil if none found." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (buffer-substring (line-beginning-position) (line-end-position)))) + (if (string-match rdebug-breakpoint-regexp s) + (substring s (match-beginning 1) (match-end 1)) + nil)))) + +(defun rdebug-toggle-breakpoint (&optional pt) + "Toggle the breakpoint at PT in the breakpoints buffer." + (interactive "d") + (save-excursion + (if pt + (goto-char pt)) + (let ((s (buffer-substring (line-beginning-position) (line-end-position)))) + (when (string-match rdebug-breakpoint-regexp s) + (let* ((enabled + (string= (substring s (match-beginning 2) (match-end 2)) "y")) + (cmd (if enabled "disable" "enable")) + (bpnum (substring s (match-beginning 1) (match-end 1)))) + (gud-call (format "%s breakpoint %s" cmd bpnum))))))) + +(defun rdebug-add-breakpoint-condition (pt) + "Add an expression as a condition to the break `rdebug' Ruby debugger." + (interactive "d") + (let ((bpnum (rdebug-get-breakpoint-number pt)) + (expr (read-string "Ruby expression for breakpoint condition: "))) + (if bpnum + (gud-call (format "condition %s %s" bpnum expr)) + (message "Breakpoint number not found")))) + + +;; ----------------------------------------------- +;; Breakpoint icon support. +;; + +;; This is a trivial implementation, it has the following shortcomings: +;; +;; * It assumes that the buffer content doesn't change, if it does it +;; will not be able to remove the icon. +;; +;; * No support for displaying an icon in a newly opened file. +;; +;; * It has no support for more than one session. + +;; Note: This is implemented on top of `gdb-ui'. In the future, it +;; would be better if that code is generalized. + +(require 'gdb-ui) + +;; This is a local variable, should not be placed in rdebug-vars.el. +(defvar rdebug-breakpoint-icons-current-state nil) + +(defun rdebug-breakpoint-remove-icon (entry) + "Remove the the source buffer the fringe breakpoint icon breakpoint ENTRY." + (if (eq (nth 0 entry) :file) + (let ((buf (find-buffer-visiting (nth 3 entry)))) + (if buf + (save-current-buffer + (set-buffer buf) + (save-excursion + (goto-line (nth 4 entry)) + (gdb-remove-breakpoint-icons (point) (point)))))))) + +(defun rdebug-breakpoint-remove-all-icons () + "Remove all breakpoint fringe icons." + (interactive) + (dolist (entry rdebug-breakpoint-icons-current-state) + (rdebug-breakpoint-remove-icon entry)) + (setq rdebug-breakpoint-icons-current-state nil)) + + +(defun rdebug-breakpoint-add-icon (entry) + (if (eq (nth 0 entry) :file) + (let ((buf (find-buffer-visiting (nth 3 entry)))) + (if buf + (save-current-buffer + (set-buffer buf) + (save-excursion + (goto-line (nth 4 entry)) + ;; Workaround for bug in `gdb-ui'. (It checks + ;; `left-fringe-width' but it doesn't interpret the + ;; `nil' value correctly. + (let ((gdb-buffer-fringe-width (car (window-fringes)))) + (gdb-put-breakpoint-icon (nth 2 entry) + (number-to-string (nth 1 entry)))))))))) + +(defun rdebug-breakpoint-list-member (file line list) + (let ((res nil)) + (dolist (entry list) + (if (and (equal file (nth 3 entry)) + (equal line (nth 4 entry))) + (setq res t))) + res)) + +;; bpts has the same representation as returned by `rdebug-breakpoint-all'. +(defun rdebug-breakpoint-update-icons (bpts) + ;; Make sure there are is only one reference for each line. + (let ((state '())) + ;; An enabled breakpoint take precedence. + (dolist (enabled '(t nil)) + (dolist (bpt bpts) + (if (and (eq (nth 0 bpt) :file) + (eq (nth 2 bpt) enabled) + (not (rdebug-breakpoint-list-member + (nth 3 bpt) (nth 4 bpt) state))) + (setq state (cons bpt state))))) + (dolist (entry rdebug-breakpoint-icons-current-state) + (unless (member entry state) + (rdebug-breakpoint-remove-icon entry))) + (dolist (entry state) + (unless (member entry rdebug-breakpoint-icons-current-state) + (rdebug-breakpoint-add-icon entry))) + (setq rdebug-breakpoint-icons-current-state state))) + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-breaks) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +(provide 'rdebug-breaks) + +;;; rdebug-breaks.el ends here diff --git a/emacs/rdebug-cmd.el b/emacs/rdebug-cmd.el new file mode 100644 index 0000000..ada316c --- /dev/null +++ b/emacs/rdebug-cmd.el @@ -0,0 +1,92 @@ +;;; rdebug-cmd.el --- Ruby debugger command buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-cmd.el 822 2008-04-27 08:28:29Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing primarily with the command buffer. + +;;; Code: + +(require 'ring) +(require 'rdebug-locring) + +(defun rdebug-command-initialization () + "Initialization of command buffer common to `rdebug' and`rdebug-track-attach'." + + ;; This opens up "Gud" menu, which isn't used since we've got our + ;; own "Debugger" menu. + ;; (set (make-local-variable 'gud-minor-mode) 'rdebug) + + (set (make-local-variable 'rdebug-call-queue) '()) + (set (make-local-variable 'rdebug-original-read-only) buffer-read-only) + (make-local-variable 'rdebug-source-location-ring-size) ; ...to global val. + (set (make-local-variable 'rdebug-source-location-ring) + (make-ring rdebug-source-location-ring-size)) + (make-local-variable 'rdebug-source-location-ring-index) + (rdebug-locring-clear) + + (gud-def gud-args "info args" "a" + "Show arguments of current stack frame.") + (gud-def gud-break "break %d%f:%l""\C-b" + "Set breakpoint at current line.") + (gud-def gud-cont "continue" "\C-r" + "Continue with display.") + (gud-def gud-down "down %p" "<" + "Down N stack frames (numeric arg).") + (gud-def gud-finish "finish" "\C-f" + "Finish executing current function.") + (gud-def gud-source-resync "up 0" "\C-l" + "Show current source window") + (gud-def gud-remove "clear %d%f:%l" "\C-d" + "Remove breakpoint at current line") + (gud-def gud-quit "quit" "Q" + "Quit debugger.") + + (gud-def gud-statement "eval %e" "\C-e" + "Execute Ruby statement at point.") + (gud-def gud-tbreak "tbreak %d%f:%l" "\C-t" + "Set temporary breakpoint at current line.") + (gud-def gud-up "up %p" + ">" "Up N stack frames to a newer frame (numeric arg).") + (gud-def gud-where "where" + "T" "Show stack trace.") + + (local-set-key [M-insert] 'rdebug-internal-short-key-mode) + (local-set-key [M-down] 'rdebug-locring-newer) + (local-set-key [M-up] 'rdebug-locring-older) + (local-set-key [M-S-down] 'rdebug-locring-newest) + (local-set-key [M-S-up] 'rdebug-locring-oldest) + ;; (local-set-key "\C-i" 'gud-gdb-complete-command) + (local-set-key "\C-c\C-n" 'comint-next-prompt) + (local-set-key "\C-c\C-p" 'comint-previous-prompt)) + +;; stopping location motion routines. + +(provide 'rdebug-cmd) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-cmd.el ends here diff --git a/emacs/rdebug-core.el b/emacs/rdebug-core.el new file mode 100644 index 0000000..c8c43b7 --- /dev/null +++ b/emacs/rdebug-core.el @@ -0,0 +1,502 @@ +;;; rdebug-core.el --- Core parts of the Ruby debugger user +;;; interface. It pulls in other parts of the debugger. + +;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id: rdebug-core.el 909 2009-03-11 18:57:08Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file implements the core of the debugger. + +;;; Code: + +;; ------------------------------------------------------------------- +;; Consistency checks. +;; + +(if (< emacs-major-version 22) + (error + "This version of rdebug.el needs at least Emacs 22 or greater - you have version %d" + emacs-major-version)) + + +;; ------------------------------------------------------------------- +;; Dependencies. +;; + +(require 'gud) +(require 'cl) + +(require 'rdebug) +(require 'rdebug-annotate) +(require 'rdebug-dbg) +(require 'rdebug-cmd) +(require 'rdebug-layouts) +(require 'rdebug-source) +(require 'rdebug-regexp) +(require 'rdebug-vars) + +(defun rdebug-get-script-name (args) + "Parse command line ARGS. + +A list containing the script name, and whether the annotate +option was set is returned. + +Initially annotate should be set to nil. Argument ARGS contains +a tokenized list of the command line." + ;; Parse the following: + ;; + ;; [ruby ruby-options] rdebug rdebug-options script-name script-options + (and args + (let ((name nil) + (annotate-p nil)) + ;; Strip of optional "ruby" or "ruby182" etc. + (when (string-match "^ruby[0-9]*$" + (file-name-sans-extension + (file-name-nondirectory (car args)))) + (pop args) + (while (and args + (string-match "^-" (car args))) + (if (member (car args) '("-e" "-r" "-I" "-C" "-F" "-K")) + (pop args)) + (pop args))) + ;; Remove "rdebug" from "rdebug --rdebug-options script + ;; --script-options" + (pop args) + ;; Skip to the first non-option argument. + (while (and args + (not name)) + (let ((arg (pop args))) + (cond + ;; Annotation or emacs option with level number. + ((or (member arg '("--annotate" "-A")) + (equal arg "--emacs")) + (setq annotate-p t) + (pop args)) + ;; Combined annotation and level option. + ((string-match "^--annotate=[0-9]" arg) + (setq annotate-p t)) + ;; Options with arguments. + ((member arg '("-h" "--host" "-p" "--port" + "-I" "--include" "-r" "--require")) + (pop args)) + ((string-match "^-" arg) + nil) + (t + (setq name arg))))) + (and name + (list name annotate-p))))) + +;; ------------------------------------------------------------------- +;; Window configuration state support. +;; + +(defun rdebug-set-window-configuration-state (state &optional dont-restore) + "Change window configuration state. + +Two states are supported, `original' and `debugger'. + +When `dont-restore' is non-nil, the old window layout is not +restored. This is used when a new layout is being drawn, for +example when the debugger starts." + (rdebug-debug-message "Setting state to %s (was %s)" + state rdebug-window-configuration-state) + (when (not (eq state rdebug-window-configuration-state)) + ;; Save the previous state. + (cond ((not (eq rdebug-window-configuration-state 'original)) + (setq rdebug-debugger-window-configuration + (current-window-configuration))) + ((eq rdebug-window-configuration-state 'original) + (setq rdebug-original-window-configuration + (current-window-configuration)))) + (unless dont-restore + ;; Switch to the saved state, + (cond + ((not (eq state 'original)) + (if rdebug-debugger-window-configuration + (set-window-configuration rdebug-debugger-window-configuration))) + ((eq state 'original) + (if rdebug-original-window-configuration + (set-window-configuration rdebug-original-window-configuration))))) + (setq rdebug-window-configuration-state state))) + + +;; have to bind rdebug-file-queue before installing the kill-emacs-hook +(defvar rdebug-file-queue nil + "Queue of Makefile temp files awaiting execution. +Currently-active file is at the head of the list.") + +(defun rdebug-goto-traceback-line (pt) + "Display the location PT in a source file of the Ruby traceback line." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (buffer-substring (line-beginning-position) (line-end-position))) + (gud-comint-buffer (current-buffer))) + (when (string-match rdebug-traceback-line-re s) + (rdebug-display-line + (substring s (match-beginning 1) (match-end 1)) + (string-to-number (substring s (match-beginning 2) (match-end 2)))) + )))) + +(defun rdebug-goto-dollarbang-traceback-line (pt) + "Display the location PT in a source file of the Ruby $! traceback line." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (buffer-substring (line-beginning-position) (line-end-position))) + (gud-comint-buffer (current-buffer))) + (when (string-match rdebug-dollarbang-traceback-line-re s) + (rdebug-display-line + (substring s (match-beginning 1) (match-end 1)) + (string-to-number (substring s (match-beginning 2) (match-end 2)))) + )))) + +;; ------------------------------------------------------------------- +;; Secondary buffers. +;; + +(require 'rdebug-secondary) +(require 'rdebug-breaks) +(require 'rdebug-frames) +(require 'rdebug-help) +(require 'rdebug-output) +(require 'rdebug-varbuf) +(require 'rdebug-watch) + + +;; ------------------------------------------------------------------- +;; Windows. +;; + +(defun rdebug-setup-windows (&optional erase) + "Create the debugger user interface window layout. + +If ERASE is non-nil, the content of the windows are erased +\(this does not apply to accumulative windows). + +This function displays the source file (or, in some cases, a +buffer list) and creates the window layout. The variable +`rdebug-window-layout-function' controls the function that is +used to perform the actual layout. + +This is only used when `rdebug-many-windows' is non-nil." + (rdebug-debug-enter "rdebug-setup-windows" + (rdebug-set-window-configuration-state 'debugger t) + (pop-to-buffer gud-comint-buffer) + (maphash + (lambda (name func) + (if erase + (let ((buf (rdebug-get-existing-buffer name gud-target-name))) + (if buf + (with-current-buffer buf + (let ((inhibit-read-only t)) + (erase-buffer)))))) + (rdebug-process-annotation name "")) + rdebug-annotation-setup-map) + (let ((buf + (cond (gud-last-last-frame + (gud-find-file (car gud-last-last-frame))) + (gud-target-name + (gud-find-file gud-target-name))))) + ;; Put a buffer in window if we can't find a source file. + (unless buf (setq buf (get-buffer-create "*scratch*"))) + (funcall rdebug-window-layout-function buf gud-target-name)))) + + +(defun rdebug-setup-windows-initially () + "Like `rdebug-setup-windows', but erase the content of accumulative windows. +This is called when the debugger starts." + (rdebug-setup-windows t)) + + +(defun rdebug-restore-debugger-window-layout () + "Restore the initial ruby debugger window layout." + (interactive) + (when rdebug-many-windows + (rdebug-setup-windows))) + +(defun rdebug-display-debugger-window-configuration () + "Switch from the \"original\" to the \"debugger\" window layout. + +The rdebug debugger remembers, and can switch between, two window layouts: + * original -- the window layout when the debugger was started. + * debugger -- the window layout of the debugger, plus all changes made + since the debugger started. + +The check-marks in the \"Window Layout\" menu indicates the +active window layout. + +The function `rdebug-display-original-window-configuration' +switch to the \"original\" window configuration. + +The function `rdebug-restore-debugger-window-layout' restores the +window layout to the state it was when the debugger started." + (interactive) + (rdebug-set-window-configuration-state 'debugger) + (message + "Type `M-x rdebug-display-original-window-configuration RET' to restore.")) + + +;;This function is called upon quitting the debugger and +;;`rdebug-many-windows' is not nil. See also +;;`rdebug-display-debugger-window-configuration'." + +(defun rdebug-display-original-window-configuration () + "Switch from the \"debugger\" to the \"original\" window layout. + +The rdebug debugger remembers, and can switch between, two window layouts: + * original -- the window layout when the debugger was started. + * debugger -- the window layout of the debugger, plus all changes made + since the debugger started. + +The check-marks in the \"Window Layout\" menu indicates the +active window layout. + +The function `rdebug-display-debugger-window-configuration' +switch to the \"debugger\" window configuration." + (interactive) + (rdebug-set-window-configuration-state 'original) + (message + "Type `M-x rdebug-display-debugger-window-configuration RET' to restore.")) + + +;; ------------------------------------------------------------------- +;; The `rdebug' command and support functions. +;; + +(defun rdebug-process-sentinel (process event) + "Restore the original window configuration when the debugger process exits." + (rdebug-debug-enter "rdebug-process-sentinel" + (rdebug-debug-message "status=%S event=%S state=%S" + (process-status process) + event + rdebug-window-configuration-state) + (gud-sentinel process event) + ;; This will "flush" the last annotation. Especially "output" + ;; (a.k.a. "starting") annotations don't have an end markers, if + ;; the last command printed something. + (if (string= event "finished\n") + (gud-rdebug-marker-filter "\032\032\n")) + ;; When the debugger process exited, when the comint buffer has no + ;; buffer process (nil). When the debugger processes is replaced + ;; with another process we should not restore the window + ;; configuration. + (when (and (or (eq rdebug-restore-original-window-configuration t) + (and (eq rdebug-restore-original-window-configuration :many) + rdebug-many-windows)) + (or (rdebug-dead-process-p) + (eq process (get-buffer-process gud-comint-buffer))) + (eq rdebug-window-configuration-state 'debugger) + (not (eq (process-status process) 'run))) + (rdebug-internal-short-key-mode-off) + (rdebug-set-window-configuration-state 'original) + (rdebug-reset-keymaps)))) + + +;; Perform initializations common to all debuggers. +;; The first arg is the specified command line, +;; which starts with the program to debug. +;; The other three args specify the values to use +;; for local variables in the debugger buffer. +(defun rdebug-common-init (rdebug-buffer-name rdebug-cmd-buffer target-name + program args + marker-filter + &optional find-file) + "Perform initializations common to all debuggers. + +RDEBUG-BUFFER-NAME is the specified command line, which starts +with the program to debug. PROGRAM, ARGS and MARKER-FILTER +specify the values to use for local variables in the debugger +buffer." + (if rdebug-cmd-buffer + (progn + (pop-to-buffer rdebug-cmd-buffer) + (when (and rdebug-cmd-buffer (get-buffer-process rdebug-cmd-buffer)) + (error "This program is already being debugged")) + (apply 'make-comint rdebug-buffer-name program nil args) + (or (bolp) (newline))) + (pop-to-buffer (setq rdebug-cmd-buffer + (apply 'make-comint rdebug-buffer-name program nil + args)))) + + ;; Since comint clobbered the mode, we don't set it until now. + (gud-mode) + (set (make-local-variable 'gud-target-name) target-name) + (set (make-local-variable 'gud-marker-filter) marker-filter) + (set (make-local-variable 'gud-minor-mode) 'rdebug) + (set (make-local-variable 'gud-last-frame) nil) + (set (make-local-variable 'gud-last-last-frame) nil) + + (let ((buffer-process (get-buffer-process (current-buffer)))) + (if buffer-process + (progn + (set-process-filter buffer-process 'gud-filter) + (set-process-sentinel buffer-process 'gud-sentinel)))) + (gud-set-buffer)) + +;;;###autoload +(defun rdebug (command-line) + "Invoke the rdebug Ruby debugger and start the Emacs user interface. + +String COMMAND-LINE specifies how to run rdebug. + +By default, the \"standard\" user window layout looks like the following: + ++----------------------------------------------------------------------+ +| Toolbar | ++-----------------------------------+----------------------------------+ +| Debugger shell | Variables buffer | ++-----------------------------------+----------------------------------+ +| | | +| Source buffer | Output buffer | +| | | ++-----------------------------------+----------------------------------+ +| Stack Frame buffer | Breakpoints buffer | ++-----------------------------------+----------------------------------+ + +The variable `rdebug-window-layout-function' can be +customized so that another layout is used. In addition to a +number of predefined layouts it's possible to define a function +to perform a custom layout. + +If `rdebug-many-windows' is nil, only a traditional debugger +shell and source window is opened. + +The directory containing the debugged script becomes the initial +working directory and source-file directory for your debugger. + +The custom variable `gud-rdebug-command-name' sets the command +and options used to invoke rdebug." + (interactive + (let ((init (buffer-file-name))) + (setq init (and init + (file-name-nondirectory init))) + (list (gud-query-cmdline 'rdebug init)))) + (rdebug-debug-enter "rdebug" + (rdebug-set-window-configuration-state 'debugger t) + ;; Parse the command line and pick out the script name and whether + ;; --annotate has been set. + (let* ((words (with-no-warnings + (split-string-and-unquote command-line))) + (script-name-annotate-p (rdebug-get-script-name + (gud-rdebug-massage-args "1" words))) + (target-name (file-name-nondirectory (car script-name-annotate-p))) + (annotate-p (cadr script-name-annotate-p)) + (cmd-buffer-name (format "rdebug-cmd-%s" target-name)) + (rdebug-cmd-buffer-name (format "*%s*" cmd-buffer-name)) + (rdebug-cmd-buffer (get-buffer rdebug-cmd-buffer-name)) + (program (car words)) + (args (cdr words)) + (gud-chdir-before-run nil)) + + ;; `gud-rdebug-massage-args' needs whole `command-line'. + ;; command-line is refered through dynamic scope. + (rdebug-common-init cmd-buffer-name rdebug-cmd-buffer target-name + program args + 'gud-rdebug-marker-filter + 'gud-rdebug-find-file) + (setq comint-process-echoes t) + + (setq rdebug-inferior-status "running") + + (rdebug-command-initialization) + + ;; Setup exit callback so that the original frame configuration + ;; can be restored. + (let ((process (get-buffer-process gud-comint-buffer))) + (when process + (unless (equal rdebug-line-width 120) + (gud-call (format "set width %d" rdebug-line-width))) + (set-process-sentinel process + 'rdebug-process-sentinel))) + + + ;; Add the buffer-displaying commands to the Gud buffer, + ;; FIXME: combine with code in rdebug-track.el; make common + ;; command buffer mode map. + (let ((prefix-map (make-sparse-keymap))) + (define-key (current-local-map) gud-key-prefix prefix-map) + (define-key prefix-map "t" 'rdebug-goto-traceback-line) + (define-key prefix-map "!" 'rdebug-goto-dollarbang-traceback-line) + (rdebug-populate-secondary-buffer-map-plain prefix-map)) + + (rdebug-populate-common-keys (current-local-map)) + (rdebug-populate-debugger-menu (current-local-map)) + + (setq comint-prompt-regexp (concat "^" rdebug-input-prompt-regexp)) + (setq paragraph-start comint-prompt-regexp) + + (setcdr (assq 'rdebug-debugger-support-minor-mode minor-mode-map-alist) + rdebug-debugger-support-minor-mode-map-when-active) + (when rdebug-many-windows + (rdebug-setup-windows-initially)) + + (run-hooks 'rdebug-mode-hook)))) + + +(defadvice gud-reset (before rdebug-reset) + "Rdebug cleanup - remove debugger's internal buffers (frame, breakpoints, etc.)." + (rdebug-breakpoint-remove-all-icons) + (dolist (buffer (buffer-list)) + (when (string-match "\\*rdebug-[a-z]+\\*" (buffer-name buffer)) + (let ((w (get-buffer-window buffer))) + (when w + (delete-window w))) + (kill-buffer buffer)))) +(ad-activate 'gud-reset) + +(defun rdebug-reset () + "Rdebug cleanup - remove debugger's internal buffers (frame, breakpoints, etc.)." + (interactive) + (rdebug-breakpoint-remove-all-icons) + (dolist (buffer (buffer-list)) + (when (string-match "\\*rdebug-[a-z]+\\*" (buffer-name buffer)) + (let ((w (get-buffer-window buffer))) + (when w + (delete-window w))) + (kill-buffer buffer)))) + +(defun rdebug-reset-keymaps() + "This unbinds the special debugger keys of the source buffers." + (interactive) + (setcdr (assq 'rdebug-debugger-support-minor-mode minor-mode-map-alist) + rdebug-debugger-support-minor-mode-map-when-deactive)) + + +(defun rdebug-customize () + "Use `customize' to edit the settings of the `rdebug' debugger." + (interactive) + (customize-group 'rdebug)) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-core) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-core.el ends here diff --git a/emacs/rdebug-dbg.el b/emacs/rdebug-dbg.el new file mode 100644 index 0000000..0952595 --- /dev/null +++ b/emacs/rdebug-dbg.el @@ -0,0 +1,62 @@ +;;; rdebug-dbg.el --- Ruby debugger frames buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-dbg.el 702 2008-02-17 22:00:36Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains internal debug trace support. + +;;; Code: + +(require 'rdebug-vars) + +(defun rdebug-debug-message (&rest args) + (if rdebug-debug-active + (let ((buf (get-buffer-create "*Xrdebug*"))) + (with-current-buffer buf + (save-excursion + (goto-char (point-max)) + ;; 32 = space. + (insert (make-string (* 4 rdebug-debug-depth) 32)) + (insert (apply #'format args)) + (insert "\n")))))) + + +(defmacro rdebug-debug-enter (str &rest body) + (declare (indent 1) (debug t)) + `(progn + (rdebug-debug-message "--> %s" ,str) + (setq rdebug-debug-depth (+ rdebug-debug-depth 1)) + (unwind-protect + (progn + ,@body) + (setq rdebug-debug-depth (max 0 (- rdebug-debug-depth 1))) + (rdebug-debug-message "<-- %s" ,str)))) + +(provide 'rdebug-dbg) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-dbg.el ends here diff --git a/emacs/rdebug-error.el b/emacs/rdebug-error.el new file mode 100644 index 0000000..a16818c --- /dev/null +++ b/emacs/rdebug-error.el @@ -0,0 +1,79 @@ +;;; rdebug-error.el --- Ruby debugger error buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-error.el 713 2008-02-21 02:56:48Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the error secondary buffer. + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-fns) +(require 'rdebug-secondary) +(require 'rdebug-source) + +(defun rdebug-display-error-buffer () + "Display the rdebug error buffer." + (interactive) + (rdebug-display-secondary-buffer "error")) + +(defvar rdebug-error-mode-map + (let ((map (make-sparse-keymap))) + (rdebug-populate-secondary-buffer-map map) + map) + "Keymap used in the error buffer in the `rdebug' Ruby debugger.") + +(defun rdebug-error-mode () + "Major mode for displaying the script error in the `rdebug' Ruby debugger. + +\\{rdebug-error-mode}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-error-mode) + (setq mode-name "RDEBUG Error") + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (use-local-map rdebug-error-mode-map) + (run-mode-hooks 'rdebug-error-mode-hook)) + +(defun rebug-setup-error-buffer (buf comint-buffer) + (rdebug-debug-enter "rebug-setup-error-buffer" + (with-current-buffer buf + (rdebug-error-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer)))) + +(defun rdebug-errmsg (msg) +;;; (with-current-buffer (rdebug-get-buffer "error" gud-target-name) +;;; (goto-char (point-max)) +;;; (insert msg)) + (message (chomp msg))) + +(provide 'rdebug-error) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-error.el ends here diff --git a/emacs/rdebug-fns.el b/emacs/rdebug-fns.el new file mode 100644 index 0000000..ef0c0f1 --- /dev/null +++ b/emacs/rdebug-fns.el @@ -0,0 +1,111 @@ +;;; rdebug-fns.el --- Ruby debugger miscellaneous functions + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-frames.el 711 2008-02-20 07:09:17Z andersl $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the frames secondary buffer. + +;;; Code: + +(require 'gud) +(require 'rdebug-vars) + +(defun chomp(string &optional multiple) + "Remove trailing \n if it's there" + (if multiple + (progn + (while (and (> (length string) 0) + (eq (elt string (- (length string) 1)) ?\n)) + (setq string (substring string 0 -1))) + string) + (if (> (length string) 0) + (let ((s string)) + (if (string= "\n" (substring s -1)) + (substring s 0 -1) + s)) + ""))) + +(defun rdebug-dead-process-p () + "Return true if the rdebug comint-process is dead or exited." + ;; FIXME? Use a variable in gud-comint-buffer's status? + (or (not gud-comint-buffer) + (null (get-buffer-process gud-comint-buffer)) + (not (member (process-status gud-comint-buffer) '(run open))))) + +(defun rdebug-get-secondary-buffer-name (name) + "Get the rdebug NAME secondary buffer. If none found return nil." + (let ((target-name + (or (and gud-comint-buffer + (buffer-local-value 'gud-target-name + gud-comint-buffer)) + gud-target-name))) + (cond ((and (string= "cmd" name) gud-comint-buffer) + (buffer-name gud-comint-buffer)) + (t (format "*rdebug-%s-%s*" name target-name))))) + +(defun rdebug-set-frame-top-arrow (buf) + "Set the fringe arrow in BUF to indicate the top frame." + (with-current-buffer buf + (setq fringe-indicator-alist + '((overlay-arrow . right-triangle))))) + +(defun rdebug-set-frame-not-top-arrow (buf) + "Set the fringe arrow in BUF to indicate a frame other than the top frame." + (with-current-buffer buf + (setq fringe-indicator-alist + '((overlay-arrow . hollow-right-triangle))))) + +(defun rdebug-set-frame-arrow (buf) + "Set the fringe arrow in buffer BUF." + (if (equal 0 rdebug-frames-current-frame-number) + (rdebug-set-frame-top-arrow buf) + (rdebug-set-frame-not-top-arrow buf))) + +;; From Emacs 23 +(unless (fboundp 'split-string-and-unquote) + (defun split-string-and-unquote (string &optional separator) + "Split the STRING into a list of strings. +It understands Emacs Lisp quoting within STRING, such that + (split-string-and-unquote (combine-and-quote-strings strs)) == strs +The SEPARATOR regexp defaults to \"\\s-+\"." + (let ((sep (or separator "\\s-+")) + (i (string-match "[\"]" string))) + (if (null i) + (split-string string sep t) ; no quoting: easy + (append (unless (eq i 0) (split-string (substring string 0 i) sep t)) + (let ((rfs (read-from-string string i))) + (cons (car rfs) + (with-no-warnings + (split-string-and-unquote (substring string (cdr rfs)) + sep)))))))) + ) + + +(provide 'rdebug-fns) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-fns.el ends here diff --git a/emacs/rdebug-frames.el b/emacs/rdebug-frames.el new file mode 100644 index 0000000..6cbabb0 --- /dev/null +++ b/emacs/rdebug-frames.el @@ -0,0 +1,230 @@ +;;; rdebug-frames.el --- Ruby debugger frames buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-frames.el 735 2008-02-29 15:24:51Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the frames secondary buffer. + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-fns) +(require 'rdebug-regexp) +(require 'rdebug-secondary) +(require 'rdebug-source) + +(defun rdebug-display-frame-buffer () + "Display the rdebug stack-frame buffer." + (interactive) + (rdebug-display-secondary-buffer "frame")) + +(defvar rdebug-frames-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [double-mouse-1] 'rdebug-goto-frame-mouse) + (define-key map [mouse-2] 'rdebug-goto-frame-mouse) + (define-key map [mouse-3] 'rdebug-goto-frame-mouse) + (define-key map [(control m)] 'rdebug-goto-frame) + (define-key map "0" 'rdebug-goto-frame-n) + (define-key map "1" 'rdebug-goto-frame-n) + (define-key map "2" 'rdebug-goto-frame-n) + (define-key map "3" 'rdebug-goto-frame-n) + (define-key map "4" 'rdebug-goto-frame-n) + (define-key map "5" 'rdebug-goto-frame-n) + (define-key map "6" 'rdebug-goto-frame-n) + (define-key map "7" 'rdebug-goto-frame-n) + (define-key map "8" 'rdebug-goto-frame-n) + (define-key map "9" 'rdebug-goto-frame-n) + (rdebug-populate-secondary-buffer-map map) + + ;; -------------------- + ;; The "Stack window" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key-after map [menu-bar debugger stack] + (cons "Stack window" submenu) + 'placeholder)) + + (define-key map [menu-bar debugger stack goto] + '(menu-item "Goto frame" rdebug-goto-frame)) + map) + "Keymap to navigate rdebug stack frames.") + +(defun rdebug-goto-frame (pt) + "Show the rdebug stack frame corresponding at PT in the rdebug stack buffer." + (interactive "d") + (save-excursion + (goto-char pt) + (let ((s (concat "-->" (buffer-substring (line-beginning-position) + (line-end-position)))) + (s2 (if (= (line-number-at-pos (line-end-position 2)) + (line-number-at-pos (point-max))) + nil + ;;else + (buffer-substring (line-beginning-position 2) + (line-end-position 2))))) + (when (or (string-match rdebug-stack-frame-regexp s) + ;; need to match 1st line last to get the match position right + (and s2 (string-match rdebug-stack-frame-2nd-regexp s2) + (string-match rdebug-stack-frame-1st-regexp s))) + (let ((frame (substring s (match-beginning 2) (match-end 2)))) + (gud-call (concat "frame " frame))))))) + +(defun rdebug-goto-frame-mouse (event) + "Show the rdebug stack frame under the mouse in the rdebug stack buffer." + (interactive "e") + (with-current-buffer (window-buffer (posn-window (event-end event))) + (rdebug-goto-frame (posn-point (event-end event))))) + +;; The following is split in two to facilitate debugging. +(defun rdebug-goto-frame-n-internal (keys) + (if (and (stringp keys) + (= (length keys) 1)) + (progn + (setq rdebug-goto-entry-acc (concat rdebug-goto-entry-acc keys)) + ;; Try to find the longest suffix. + (let ((acc rdebug-goto-entry-acc)) + (while (not (string= acc "")) + (if (not (rdebug-goto-entry-try acc)) + (setq acc (substring acc 1)) + (gud-call (format "frame %s" acc)) + ;; Break loop. + (setq acc ""))))) + (message "`rdebug-goto-frame-n' must be bound to a number key"))) + +(defun rdebug-goto-frame-n () + "Go to the frame number indicated by the accumulated numeric keys just entered. + +This function is usually bound to a numeric key in a 'frame' +secondary buffer. To go to an entry above 9, just keep entering +the number. For example, if you press 1 and then 9, frame 1 is selected +\(if it exists) and then frame 19 (if that exists). Entering any +non-digit will start entry number from the beginning again." + (interactive) + (if (not (eq last-command 'rdebug-goto-frame-n)) + (setq rdebug-goto-entry-acc "")) + (rdebug-goto-frame-n-internal (this-command-keys))) + +(defun rdebug-frames-match-current-line (limit) + (and rdebug-frames-current-frame-number + (re-search-forward + (concat "^ *#" + (number-to-string rdebug-frames-current-frame-number) + ;; At least one space (so that we don't match #1 when looking for #10). + " +" + ;; The entire line. + ".*" + "\n" + ;; And the next, if this entry was split into two. + "\\( *[^# ].*$\\)?") limit t))) + +(defvar rdebug-frames-current-frame-face 'highlight) + +;; Example of frame buffer content: +;; +;; #0 Integer.under_cover at line test.rb:13 +;; #1 ClassA::Nested::DeepDown.under_cover(p#ClassA::Nested::DeepD...) +;; at line test.rb:12 +;; #2 Object.sune(s#String, i#Fixnum) at line test.rb:24 +;; #3 at line test.rb:27 + +(defvar rdebug-frames-font-lock-keywords + '( + ;; Parameters and first type entry. + ("\\<\\([a-zA-Z_][a-zA-Z0-9_]*\\)#\\([a-zA-Z_][a-zA-Z0-9_]*\\)\\>" + (1 font-lock-variable-name-face) + (2 font-lock-type-face)) + ;; "::Type", which occurs in class name of function and in parameter list. + ("::\\([a-zA-Z_][a-zA-Z0-9_]*\\)" + (1 font-lock-type-face)) + ;; The frame number and first type name, if present. + ("^ *#\\([0-9]+\\) *\\(\\([a-zA-Z_][a-zA-Z0-9_]*\\)[.:]\\)?" + (1 font-lock-constant-face) + (3 font-lock-type-face nil t)) ; t means optional. + ;; File name and line number. + ("at line \\(.*\\):\\([0-9]+\\)$" + (1 font-lock-warning-face) + (2 font-lock-constant-face)) + ;; Function name. + ("\\<\\([a-zA-Z_][a-zA-Z0-9_]*\\)\\.\\([a-zA-Z_][a-zA-Z0-9_]*\\)" + (1 font-lock-type-face) + (2 font-lock-function-name-face)) + (rdebug-frames-match-current-line + (0 rdebug-frames-current-frame-face append))) + "Font-lock rules for the stack frame window in `rdebug'.") + +(defun rdebug-frames-mode () + "Major mode for displaying the stack trace in the `rdebug' Ruby debugger. +\\{rdebug-frames-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-frames-mode) + (setq mode-name "RDEBUG Stack Frames") + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (use-local-map rdebug-frames-mode-map) + (set (make-local-variable 'font-lock-defaults) + '(rdebug-frames-font-lock-keywords)) + (run-mode-hooks 'rdebug-frames-mode-hook)) + +;; Note: This function can't restore the original point alone, since +;; the point is already at the end of the buffer when this is called. +(defun rdebug-setup-frame-buffer (buf comint-buffer) + "Find the current frame and display the corresponding source line. + +Also, cleans the buffer somewhat and sets up help for the font-lock rules." + (rdebug-debug-enter "rdebug-setup-stack-buffer" + (with-current-buffer buf + (let ((inhibit-read-only t) + (current-frame-number 0)) + (rdebug-frames-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer) + (goto-char (point-min)) + (when (re-search-forward "-->" nil t) + (beginning-of-line) + (setq overlay-arrow-position (make-marker)) + (set-marker overlay-arrow-position (point)) + (when (looking-at rdebug-stack-frame-1st-regexp) + (setq current-frame-number + (string-to-number + (match-string rdebug-stack-frame-number-group))) + (set (make-local-variable 'rdebug-frames-current-frame-number) + current-frame-number) + (with-current-buffer comint-buffer + (setq rdebug-frames-current-frame-number current-frame-number)) + (when gud-last-frame + (rdebug-set-frame-arrow (gud-find-file (car gud-last-frame)))) + (rdebug-set-frame-arrow buf))) + ;; Remove initial ' ' or '-->'. + (save-excursion + (goto-char (point-max)) + (beginning-of-line) + (if (> (point) 4) + (delete-rectangle 4 (point)))))))) + +(provide 'rdebug-frames) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-frames.el ends here diff --git a/emacs/rdebug-gud.el b/emacs/rdebug-gud.el new file mode 100644 index 0000000..d4f6086 --- /dev/null +++ b/emacs/rdebug-gud.el @@ -0,0 +1,242 @@ +;;; rdebug-gud.el --- rdebug interface to gud. + +;; Copyright (C) 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id: rdebug-gud.el 821 2008-04-25 02:54:44Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains rdebug Emacs routines which interface with gud. + +;;; Code: + +;; ------------------------------------------------------------------- +;; Dependencies. +;; + +(require 'gud) +(require 'rdebug-error) +(require 'rdebug-fns) +(require 'rdebug-regexp) +(require 'rdebug-vars) + + +(defun gud-rdebug-massage-args (file args) + "Change FILE and list ARGS before running the debugger. + +gud requires this routine to be defined." + args) + + +(defun gud-rdebug-find-file (file) + "`rdebug' and `gud' call this with FILE when they encounter a Ruby program file." + + (find-file-noselect file 'nowarn)) + +(defun rdebug-display-line (file line &optional move-arrow) + "Arrange for marker to appear in at FILE and LINE. +The line marker might appear in the Emacs fringe or as an overlay arroe. +Optional argument MOVE-ARROW indicates whether to move any previous indicator." + (if file + (let ((oldpos (and gud-overlay-arrow-position + (marker-position gud-overlay-arrow-position))) + (oldbuf (and gud-overlay-arrow-position + (marker-buffer gud-overlay-arrow-position)))) + (gud-display-line file line) + (unless move-arrow + (when gud-overlay-arrow-position + (set-marker gud-overlay-arrow-position oldpos oldbuf)))))) + +(defun rdebug-stepping (step-or-next &optional arg) + (or arg (setq arg 1)) + ;;(if (not (member '('rdebug-next 'rdebug-step 'digit-argument) last-command)) + ;; (setq rdebug-stepping-prefix "")) + (unless (member rdebug-stepping-prefix '("" "+" "-")) + (setq rdebug-stepping-prefix "")) + (rdebug-call (format "%s%s %d" step-or-next rdebug-stepping-prefix arg))) + + + +;; ------------------------------------------------------------------- +;; Rdebug commands. +;; + +(defun rdebug-call (cmd) + "Run a debugger command with some error checking." + (if (rdebug-dead-process-p) + (rdebug-errmsg + "Can't find a live debugger process buffer to feed the command to.") + (gud-call cmd))) + +(defun rdebug-call-return (cmd &rest options) + "Register a debugger command whose output should be handled specially. + +OPTIONS is zero or more indicators what should happen with the +output. The following are supported: + * :tooltip -- Show the result in a tool-tip. + * :info -- Show the result in the info secondary buffer." + (if (rdebug-dead-process-p) + (rdebug-errmsg + "Can't find a live debugger process buffer to feed the command to.") + (with-current-buffer gud-comint-buffer + (setq rdebug-call-queue + (append rdebug-call-queue (list (cons cmd options)))) + (gud-call cmd)))) + +(defun rdebug-continue (&optional arg) + "Run a debugger \"continue\" command. + +With a numeric ARG, continue to that line number of the current file." + (interactive "p") + (if arg + (rdebug-call (format "continue %d" arg)) + (rdebug-call (format "continue")))) + + +(defun rdebug-next (&optional arg) + "Run a debugger \"next\" command, respecting `rdebug-stepping-prefix'. + +With a numeric ARG, continue to that line number of the current file." + (interactive "p") + (rdebug-stepping "next" arg)) + +(defvar rdebug-stepping-prefix "" + "The kind of stepping modifier that is desired. + +This variable will have a string value which is either \"\", +\"+\", or \"-\"; this string is be appended to the debugger +stepping commands (\"next\", or \"step\").") + +(defun rdebug-print-cmd (expr &optional cmd) + "Run a debugger print (pl, ps, pp, p) command on `EXPR'; `CMD' is the command to run." + (interactive "s") + (unless cmd (setq cmd "pp")) + (rdebug-call-return (format "%s %s " cmd expr) :tooltip)) + +(defun rdebug-print-list-region (from to) + "Run a debugger \"pl\" command on the marked region." + (interactive "r") + (if (> from to) + (let ((tem to)) + (setq to from from tem))) + (rdebug-print-cmd (buffer-substring from to) "pl")) + +(defun rdebug-print-region (from to) + "Run a debugger \"p\" command on the marked region." + (interactive "r") + (if (> from to) + (let ((tem to)) + (setq to from from tem))) + (rdebug-print-cmd (buffer-substring from to) "p")) + +(defun rdebug-print-sorted-region (from to) + "Run a debugger \"ps\" command on the marked region." + (interactive "r") + (if (> from to) + (let ((tem to)) + (setq to from from tem))) + (rdebug-print-cmd (buffer-substring from to) "ps")) + +(defun rdebug-pretty-print-region (from to) + "Run a debugger \"pp\" command on the marked region." + (interactive "r") + (if (> from to) + (let ((tem to)) + (setq to from from tem))) + (rdebug-print-cmd (buffer-substring from to) "pp")) + + +;; +;; The following two commands should be seen as proof-of-concept +;; functions for the info buffer. +;; + +(defun rdebug-pretty-print-to-buffer (s) + "Pretty print expression to the info buffer." + (interactive "sPretty print: ") + (rdebug-call-return (format "pp %s" s) :info)) + +(defun rdebug-pretty-print-region-to-buffer (from to) + "Pretty print expression in region to the info buffer." + (interactive "r") + (rdebug-call-return (format "pp %s" (buffer-substring from to)) :info)) + + + +(defun rdebug-quit () + "Kill the debugger process associated with the current buffer. + +When `rdebug-many-windows' is active, the original window layout +is restored." + (interactive) + (if (yes-or-no-p "Really quit? ") + (rdebug-call "quit unconditionally"))) + +(defun rdebug-restart () + "Restart the debugged Ruby script. + +An exec restart is used." + (interactive) + (if (yes-or-no-p "Restart? ") + (rdebug-call "restart"))) + +(defun rdebug-set-stepping-prefix () + "Set the granularity of stepping on the subsequent 'next' or 'step' command. +As long as repeated next or step commands are given, they inherit this setting." + (interactive) + (setq rdebug-stepping-prefix (this-command-keys))) + +(defun rdebug-step (&optional arg) + "Run a debugger \"next\" command, respecting `rdebug-stepping-prefix'. + +With a numeric ARG, continue to that line number of the current file." + (interactive "p") + (rdebug-stepping "step" arg)) + +(defun rdebug-newer-frame () + "Run a debugger \"down\" command to an newer frame. + +If we try to go down from frame 0, wrap to the end of the file" + (interactive) + (let* ((buf-name (rdebug-get-secondary-buffer-name "frame")) + (buf (or (get-buffer buf-name) (current-buffer)))) + (with-current-buffer buf + ;; Should we add a mode to disable wrapping? + (if (equal rdebug-frames-current-frame-number 0) + (rdebug-call "frame -1") + (rdebug-call "down 1"))))) + +(defun rdebug-older-frame () + "Run a debugger \"up\" command to an older frame." + (interactive) + (let* ((buf-name (rdebug-get-secondary-buffer-name "frame")) + (buf (or (get-buffer buf-name) (current-buffer)))) + (with-current-buffer buf + ;; Should we add a mode to disable wrapping? + (rdebug-call "up 1")))) + +(provide 'rdebug-gud) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-gud.el ends here diff --git a/emacs/rdebug-help.el b/emacs/rdebug-help.el new file mode 100644 index 0000000..7782866 --- /dev/null +++ b/emacs/rdebug-help.el @@ -0,0 +1,104 @@ +;;; rdebug-help.el --- Ruby debugger help + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-help.el 711 2008-02-20 07:09:17Z andersl $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the help buffer. + +;;; Code: + +(defvar rdebug-secondary-window-help-mode-map + (let ((map (make-sparse-keymap))) + (suppress-keymap map) + (rdebug-populate-secondary-buffer-map map) + map) + "Keymap used in the help buffer in the `rdebug' Ruby debugger.") + +(defun rdebug-secondary-window-help-mode () + "Major mode for the secondary buffer help text in the `rdebug' Ruby debugger. + +\\{rdebug-secondary-window-help-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-secondary-window-help-mode) + (setq mode-name "RDEBUG Help") + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (use-local-map rdebug-secondary-window-help-mode-map) + (run-mode-hooks 'rdebug-secondary-window-help-mode-hook)) + +(defun rdebug-display-secondary-window-help-buffer () + "Display the rdebug help buffer." + (interactive) + (rdebug-display-secondary-buffer "help")) + +(defun rdebug-setup-secondary-window-help-buffer (buf comint-buffer) + (rdebug-debug-enter "rdebug-setup-secondary-window-help-buffer" + (with-current-buffer buf + (rdebug-secondary-window-help-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer) + (insert "\ + +This is a rdebug secondary window, you can use it to watch a +number of help buffers. Use capital letters to switch between the +available buffers. Lower case letters (and other key +combinations) are used to issue buffer-specific commands. + +Press `C-h m' for more help, when the individual buffers are visible. + + B - Breakpoints buffer. + C - Command buffer (the debugger shell) + O - Output window + S - go to source frame + T - Stack trace buffer + V - Variables buffer + W - Watch buffer + + SPC - step (into) + + - set for step+ and next+ + - - set for step- and next- + _ - set to remove +/- + c - continue + f - finish (step out) + n - next (step over) + p - print + q - quit + r - run (restart) + R - run (restart) + s - step (into) + + > - go down frame (with numeric argument goes down that many frames) + < - go up one frame (with numeric argument goes down that many frames) + + ? - This help text. +")))) + +(provide 'rdebug-help) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-help.el ends here diff --git a/emacs/rdebug-info.el b/emacs/rdebug-info.el new file mode 100644 index 0000000..af09933 --- /dev/null +++ b/emacs/rdebug-info.el @@ -0,0 +1,83 @@ +;;; rdebug-info.el --- This file contains code dealing with the Ruby +;;; debugger's info secondary buffer. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-breaks.el 670 2008-02-06 18:15:28Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-gud) +(require 'rdebug-regexp) +(require 'rdebug-secondary) +(require 'rdebug-source) +(require 'rdebug-vars) + +(defun rdebug-display-info-buffer () + "Display the rdebug breakpoints buffer." + (interactive) + (rdebug-display-secondary-buffer "info")) + +(defvar rdebug-info-mode-map + (let ((map (make-sparse-keymap))) + (rdebug-populate-secondary-buffer-map map) + map) + "Keymap for the Rdebug info secondary buffer.") + +(defun rdebug-info-mode () + "Major mode for Ruby debugger info buffer. + +\\{rdebug-info-mode-map}" + (kill-all-local-variables) + (setq major-mode 'rdebug-info-mode) + (setq mode-name "RDEBUG Info") + (use-local-map rdebug-info-mode-map) + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (run-mode-hooks 'rdebug-info-mode-hook)) + +(defun rdebug-setup-info-buffer (buf comint-buffer) + "Setup the Rdebug debugger info buffer." + (rdebug-debug-enter "rdebug-setup-info-buffer" + (with-current-buffer buf + (let ((inhibit-read-only t) + (old-line-number (buffer-local-value 'rdebug-current-line-number + buf))) + (rdebug-info-mode) + (goto-line old-line-number))))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-info) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-info.el ends here diff --git a/emacs/rdebug-layouts.el b/emacs/rdebug-layouts.el new file mode 100644 index 0000000..74329f8 --- /dev/null +++ b/emacs/rdebug-layouts.el @@ -0,0 +1,180 @@ +;;; rdebug-layouts.el --- Ruby debugger window layouts. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-layouts.el 723 2008-02-24 04:51:39Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This is file contains the window layouts that come with rdebug; the +;; code where can be consulted as a guide for creating other window +;; layouts. + +;; See the manual and the file `rdebug.el' for overall information on +;; the ruby debugger rdebug. + +;;; Code: + +(defun rdebug-get-buffer (name script-name) + "Return a rdebug buffer for displaying NAME when debugging SCRIPT-NAME. +If the buffer doesn't exists it is created." + (get-buffer-create (format "*rdebug-%s-%s*" name script-name))) + + +(defun rdebug-get-existing-buffer (name script-name) + "Return a rdebug buffer for displaying NAME when debugging SCRIPT-NAME. +Return nil if the buffer doesn't exists." + (get-buffer (format "*rdebug-%s-%s*" name script-name))) + + +(defun rdebug-window-layout-conservative (src-buf name) + "A conservative rdebug window layout with three windows. + +This window layout mimics the traditional debugger shell and +source window layout, it only add one secondary window. +Initially, the secondary window displays output of the debugged +process, but any secondary buffer can be displayed, press `?' in +the window for more details. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (split-window-horizontally) + (other-window 1) + (switch-to-buffer src-buf) + (other-window 1) + (when rdebug-use-separate-io-buffer + (split-window nil 20) + (set-window-buffer + (selected-window) (rdebug-get-buffer "output" name))) + (other-window 1)) + +(defun rdebug-window-layout-rocky (src-buf name) + "Rocky's window layout. + +3 windows. The source window is on top 4/5 of height. The +bottom is split between the command windows and a stack window. + +See `rdebug' for more information. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (split-window nil ( / ( * (window-height) 4) 5)) + (set-window-buffer + (selected-window) src-buf) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "frame" name)) + (split-window-horizontally) + (set-window-buffer + (selected-window) (rdebug-get-buffer "cmd" name)) + (goto-char (point-max))) + +(defun rdebug-window-layout-rocky2 (src-buf name) + "This layout is standard window without the output window, see `rdebug'. +for more information. +Argument SRC-BUF is the NAME of the buffer containing the Ruby source program that was initially run." + (delete-other-windows) + (split-window nil ( / ( * (window-height) 3) 4)) + (set-window-buffer + (selected-window) src-buf) + (split-window nil ( / (window-height) 3)) + (split-window-horizontally) + (set-window-buffer + (selected-window) (rdebug-get-buffer "frame" name)) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "variables" name)) + (other-window 1) + (switch-to-buffer src-buf) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "cmd" name)) + (goto-char (point-max))) + +(defun rdebug-window-layout-stack-of-windows (src-buf name) + "A rdebug window layout with several secondary windows to the right. +The debugger shell and the source code window is to the left. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (split-window-horizontally) + (split-window nil 20) + (set-window-buffer + (selected-window) (rdebug-get-buffer "cmd" name)) + (other-window 1) + (switch-to-buffer src-buf) + (other-window 1) + (split-window) + (split-window) + (set-window-buffer + (selected-window) (rdebug-get-buffer "variables" name)) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "frame" name)) + (when rdebug-use-separate-io-buffer + (other-window 1) + (split-window) + (set-window-buffer + (selected-window) (rdebug-get-buffer "output" name))) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "breakpoints" name)) + (other-window 1)) + +;; The default layout +(defun rdebug-window-layout-standard (src-buf name) + "The default rdebug window layout, see `rdebug' for more information. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (split-window nil ( / ( * (window-height) 3) 4)) + (split-window nil ( / (window-height) 3)) + (split-window-horizontally) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "variables" name)) + (other-window 1) + (switch-to-buffer src-buf) + (when rdebug-use-separate-io-buffer + (split-window-horizontally) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "output" name))) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "frame" name)) + (split-window-horizontally) + (other-window 1) + (set-window-buffer + (selected-window) (rdebug-get-buffer "breakpoints" name)) + (other-window 1) + (goto-char (point-max))) + + +(defun rdebug-window-layout-no-shell (src-buf name) + "A rdebug window layout without a shell window. +Argument SRC-BUF the buffer containing the Ruby source program that was initially run. NAME is the name of that buffer." + (delete-other-windows) + (set-window-buffer + (selected-window) (rdebug-get-buffer "watch" name)) + (rdebug-window-layout-standard src-buf name)) + +(provide 'rdebug-layouts) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-layouts.el ends here diff --git a/emacs/rdebug-locring.el b/emacs/rdebug-locring.el new file mode 100644 index 0000000..b90b3fd --- /dev/null +++ b/emacs/rdebug-locring.el @@ -0,0 +1,118 @@ +;;; rdebug-locring.el --- Ruby debugger location ring + +;; Copyright (C) 2008, 2009 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-locring.el 917 2009-03-31 09:49:37Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file manages a ring of (recently stopped) positions to allow +;; the programmer to move back and forth between them. + +;;; Code: + +(defvar rdebug-source-location-ring nil + "Ring of the last `rdebug-source-location-ring-size' positions we've stopped aft.") + +(defvar rdebug-source-location-ring-index -1 + "Position in `rdebug-source-location-ring' of where we are.") + +(defun rdebug-locring-add (frame location-history-ring) + "Add FRAME to LOCATION-HISTORY-RING if we are on the top frame and have a frame to add." + ;; Switching frames shouldn't save a new ring + ;; position. Also make sure no position is different. + ;; Perhaps duplicates should be controlled by an option. + (unless (and (not (ring-empty-p location-history-ring)) + (equal (ring-ref location-history-ring + (ring-length location-history-ring)) frame)) + (ring-insert-at-beginning location-history-ring frame))) + +(defun rdebug-locring-clear () + "Clear out all source locations in `Go to the source location of the first stopping point." + (interactive) + (setq rdebug-source-location-ring-index -1) + (while (not (ring-empty-p rdebug-source-location-ring)) + (ring-remove rdebug-source-location-ring))) + +(defun rdebug-locring-goto (ring-position) + "Go the source position RING-POSITION in the stopping history." + (interactive "NSource location ring position (0 is oldest): ") + (with-current-buffer gud-comint-buffer + (setq rdebug-source-location-ring-index ring-position) + (let* ((frame (ring-ref rdebug-source-location-ring ring-position)) + (file (car frame)) + (line (cdr frame))) + (when file + (rdebug-display-line file line) + (message (format "%d %s:%d" rdebug-source-location-ring-index + file line)))))) + +(defun rdebug-locring-newer () + "Cycle through source location stopping history to get the next newer (more recently visited) location." + (interactive) + (with-current-buffer gud-comint-buffer + (if (equal (+ 1 rdebug-source-location-ring-index) + (ring-length rdebug-source-location-ring)) + (progn + (message "At newest - Will set to wrap to oldest.") + (setq rdebug-source-location-ring-index -1)) + ;; else + (rdebug-locring-goto + (if (> rdebug-source-location-ring-index + (ring-length rdebug-source-location-ring)) + 0 + ;; else + (ring-plus1 rdebug-source-location-ring-index + (ring-length rdebug-source-location-ring))))))) + +(defun rdebug-locring-newest () + "Go to the source location of the first stopping point." + (interactive) + (rdebug-locring-goto (- (ring-length rdebug-source-location-ring) 1))) + +(defun rdebug-locring-older () + "Cycle through source location stopping history to get the next older (least recently visited) location." + (interactive) + (with-current-buffer gud-comint-buffer + (if (equal rdebug-source-location-ring-index 0) + (progn + (message "At oldest - Will set to wrap to newest.") + (setq rdebug-source-location-ring-index + (+ 1 (ring-length rdebug-source-location-ring)))) + ;; else + (rdebug-locring-goto + (if (or (not rdebug-source-location-ring-index) + (< rdebug-source-location-ring-index 0)) + 0 + ;; else + (ring-minus1 rdebug-source-location-ring-index + (ring-length rdebug-source-location-ring))))))) + +(defun rdebug-locring-oldest () + "Go to the oldest source position location." + (interactive) + (ring-ref rdebug-source-location-ring 0)) + +(provide 'rdebug-locring) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-locring.el ends here diff --git a/emacs/rdebug-output.el b/emacs/rdebug-output.el new file mode 100644 index 0000000..8c475dc --- /dev/null +++ b/emacs/rdebug-output.el @@ -0,0 +1,106 @@ +;;; rdebug-output.el --- Ruby debugger output buffer + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-output.el 711 2008-02-20 07:09:17Z andersl $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file contains code dealing with the output secondary buffer. + +;;; Code: + +(require 'rdebug-dbg) +(require 'rdebug-secondary) + +(defun rdebug-display-output-buffer () + "Display the rdebug output buffer." + (interactive) + (rdebug-display-secondary-buffer "output")) + +;; FIXME add a macro to toggle read-only and run command. +(defun rdebug-output-add-divider () + (interactive "") + (save-excursion + (goto-char (point-max)) + (setq buffer-read-only nil) + ;; FIXME Cooler would be to pick up stack position in stack line + ;; and prepend a buffer-local marker number + (insert (format "%d: ============================\n" + rdebug-output-marker-number)) + (setq rdebug-output-marker-number (+ rdebug-output-marker-number 1)) + (setq buffer-read-only t))) + +(defun rdebug-output-delete-output () + (interactive) + (setq buffer-read-only nil) + (delete-region (point-min) (point-max)) + (setq buffer-read-only t)) + +(defun rdebug-output-undo () ;FIXME make more global? + (interactive "") + (setq buffer-read-only nil) + (undo) + (setq buffer-read-only t)) + +(defvar rdebug-output-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "d" 'rdebug-output-delete-output) + (define-key map "t" 'rdebug-goto-traceback-line) + (define-key map "!" 'rdebug-goto-dollarbang-traceback-line) + (define-key map "=" 'rdebug-output-add-divider) + (define-key map "\C-_" 'rdebug-output-undo) ; FIXME get from keymap + (define-key map "u" 'rdebug-output-undo) + (suppress-keymap map) + (rdebug-populate-secondary-buffer-map map) + map) + "Keymap used in the output buffer in the `rdebug' Ruby debugger.") + +(defun rdebug-output-mode () + "Major mode for displaying the script output in the `rdebug' Ruby debugger. + +\\{rdebug-output-mode}" + (interactive) + (let ((old-marker-number rdebug-output-marker-number)) + (kill-all-local-variables) + (setq major-mode 'rdebug-output-mode) + (setq mode-name "RDEBUG Output") + (setq buffer-read-only t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (set (make-local-variable 'rdebug-accumulative-buffer) t) + (use-local-map rdebug-output-mode-map) + (set (make-local-variable 'rdebug-output-marker-number) old-marker-number) + (run-mode-hooks 'rdebug-output-mode-hook))) + +(defun rdebug-setup-output-buffer (buf comint-buffer) + (rdebug-debug-enter "rdebug-setup-output-buffer" + (with-current-buffer buf + (rdebug-output-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer)))) + +(provide 'rdebug-output) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-output.el ends here diff --git a/emacs/rdebug-regexp.el b/emacs/rdebug-regexp.el new file mode 100644 index 0000000..fe7b043 --- /dev/null +++ b/emacs/rdebug-regexp.el @@ -0,0 +1,118 @@ +;;; rdebug-regexp.el --- Ruby debugger regular expressions + +;; Copyright (C) 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id: rdebug-regexp.el 724 2008-02-24 16:14:52Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; Here we have regular expressions and names for matched patterns +;; of those regular expressions. + +;;; Code: + +;; ------------------------------------------------------------------- +;; Variables defining regular expressions (regexp:s). +;; + +(defconst gud-rdebug-marker-regexp + "\\(?:source \\)?\\(\\(?:[a-zA-Z]:\\)?[^:\n]*\\):\\([0-9]*\\).*\n" + "Regular expression used to find a file location given by rdebug. + +Program-location lines look like this: + source /tmp/gcd.rb:29: gcd + /tmp/gcd.rb:29: gcd + source /tmp/gcd.rb:29 + source C:/tmp/gcd.rb:29 + source \\sources\\capfilterscanner\\capanalyzer.rb:3: ") + +(defconst rdebug-annotation-end-regexp + "\n" + "Regular expression to match the end of an annotation.") + +;; Examples of annotations: +;; ^Z^Z\n +;; ^Z^Zfoo\n +;; ^Z^Zpre-prompt\n +;; ^Z^Zsource foo.rb:10\n + +(defconst rdebug-annotation-start-regexp + "\\(\\([a-z][-a-z]*\\)?\n\\|source \\)" + "Regular expression to match the start of an annotation.") + +(defconst rdebug-breakpoint-regexp + "^\\ +\\([0-9]+\\) \\([yn]\\) +at +\\(.+\\):\\([0-9]+\\)\\( if .*\\)?$" + "Regexp to recognize breakpoint lines in rdebug breakpoint buffers.") + +(defconst rdebug-marker-regexp-file-group 2 + "Group position in `rdebug-position-regexp' that matches the file name.") + +(defconst rdebug-marker-regexp-line-group 3 + "Group position in `rdebug-position-regexp' that matches the line number.") + +(defconst rdebug-position-regexp + "\\(\\)\\([-a-zA-Z0-9_/.]*\\):\\([0-9]+\\)" + "Regular expression for a rdebug position.") + +(defconst rdebug-traceback-line-re + "^[ \t]+from \\([^:]+\\):\\([0-9]+\\)\\( in `.*'\\)?" + "Regular expression that describes a Ruby traceback line.") + +(defconst rdebug-dollarbang-traceback-line-re + "^[ \t]+[[]?\\([^:]+\\):\\([0-9]+\\):in `.*'" + "Regular expression that describes a Ruby traceback line from $! list.") + +(defconst rdebug-stack-frame-1st-regexp + "^\\(-->\\| \\) +#\\([0-9]+\\)\\(.*\\)" + "Regexp to match the first line of a stack frame in rdebug stack buffers.") + +(defconst rdebug-stack-frame-number-group 2 + "The group position in `rdebug-stack-frame-1st-regexp' that matches the frame number.") + +(defconst rdebug-stack-frame-2nd-regexp + "\s+at line +\\([^:]+\\):\\([0-9]+\\)$" + "Regexp to match the second line of a stack frame in rdebug stack buffers.") + +(defconst rdebug-stack-frame-2nd-file-group 1 + "Group position in `rdebug-stack-frame-2nd-regexp' that matches the file name.") + +(defconst rdebug-stack-frame-2nd-line-group 2 + "Group position in `rdebug-stack-frame-2nd-regexp' that matches the line number.") +(defconst rdebug-stack-frame-regexp + (concat rdebug-stack-frame-1st-regexp rdebug-stack-frame-2nd-regexp) + "Regexp to recognize a stack frame line in rdebug stack buffers.") + +(defconst rdebug-stack-frame-file-group 4 + "Group position in `rdebug-stack-frame-regexp' that matches the file name.") + +(defconst rdebug-stack-frame-line-group 5 + "Group position in `rdebug-stack-frame-regexp' that matches the line number.") + +(defconst rdebug-input-prompt-regexp "(+rdb:\\([0-9]+\\|post-mortem\\)) " + "Regular expression to recognize a rdebug prompt. Some uses may prepend an anchor to the front.") + +(provide 'rdebug-regexp) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-regexp.el ends here diff --git a/emacs/rdebug-secondary.el b/emacs/rdebug-secondary.el new file mode 100644 index 0000000..f3a7961 --- /dev/null +++ b/emacs/rdebug-secondary.el @@ -0,0 +1,260 @@ +;;; rdebug-secondary.el --- Rdebug support windows. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-secondary.el 733 2008-02-29 04:34:44Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; Key bindings and menu for secondary buffers. + +;;; Code: + +(require 'rdebug) + +(defun rdebug-populate-secondary-buffer-map (map) + "Bind all common keys and menu used in the rdebug secondary buffers. +This includes the keys bound to `gud-key-prefix' (typically C-x +C-a)." + (rdebug-populate-secondary-buffer-map-plain map) + (rdebug-populate-common-keys map) + (rdebug-populate-debugger-menu map) + (let ((prefix-map (make-sparse-keymap))) + (rdebug-populate-secondary-buffer-map-plain prefix-map) + (define-key map gud-key-prefix prefix-map))) + + +(defun rdebug-display-cmd-buffer () + "Display the rdebug debugger command buffer." + (interactive) + (rdebug-display-secondary-buffer "cmd")) + +(defun rdebug-pick-secondary-window-categorize (win name orig-win) + "Return how suiteable this window is to display the a secondary buffer. +The higher score the better." + (let ((buffer (window-buffer win))) + (save-current-buffer + (set-buffer buffer) + (cond (rdebug-secondary-buffer + (cond ((eq win orig-win) + ;; If the user issued the command inside a + ;; secondary window, use that window. + 5) + ((and (member name '("variables" "watch")) + (memq major-mode '(rdebug-variables-mode + rdebug-watch-mode))) + ;; Let "Watch" and "Variables" switch content. + 4) + (t + ;; Any other secondary window. + 3))) + ((eq major-mode 'ruby-mode) + ;; Avoid source windows. + 0) + ((eq major-mode 'gud-mode) + ;; Avoid the debugger shell window. + 1) + (t + ;; Just any other window. + 2))))) + + +(defun rdebug-display-secondary-buffer (name) + "Display one of the rdebug secondary buffers. +If the buffer doesn't exist, do nothing. If the buffer is already +displayed, switch to it. Otherwise if the current buffer is a +secondary buffer, bury it replacing with the requested +buffer. Failing that, if there is secondary buffer visible, that +is replaced instead. And finally failing all of the preceding, +we'll just pick a visible buffer to bury and replace." + (let* ((buf-name (rdebug-get-secondary-buffer-name name)) + (buf (get-buffer buf-name)) + (orig-win (selected-window))) + (if (null buf) + (message "Buffer %s not found" buf-name) + ;; Find a suitable window to display the buffer in. + (let ((win (get-buffer-window buf (selected-frame)))) + (if win + ;; Buffer already displayed, switch to it. + (select-window win) + ;; + (let ((candidate nil) + (candidate-score -1)) + (dolist (win (window-list (selected-frame))) + (let ((score (rdebug-pick-secondary-window-categorize + win name orig-win))) + (if (> score candidate-score) + (progn + (setq candidate win) + (setq candidate-score score))))) + (select-window candidate))))) + (switch-to-buffer buf))) + + +;; Note: The generic `gud' framework contains special code to handle +;; this for GDB (see `gud-display-line') which we, unfortuately can't +;; use. Instead, we call `rdebug-pick-source-window' from +;; `gud-rdebug-marker-filter'. When gud becomes more generic we could +;; hopefully solve this in another way. +;; +;; The machanism is that `rdebug-pick-source-window' displays the +;; source file in the window of our choice, and gud kindly re-uses +;; that window. + + +(defun rdebug-display-source-window-categorize (win) + "Return how suitable this window WIN is to display the source buffer. +The higher score the better." + (let ((buffer (window-buffer win))) + (cond ((eq buffer gud-comint-buffer) + 0) + ((buffer-local-value 'rdebug-secondary-buffer buffer) + 1) + ((eq (buffer-local-value 'major-mode buffer) 'ruby-mode) + 3) ; Pick me! Pick me! + (t + 2)))) + +(defun rdebug-display-pick-source-window () + "Return the window that should get replaced by the source window." + (rdebug-debug-enter "rdebug-display-pick-source-window" + (let ((candidate nil) + (candidate-score -1)) + (dolist (win (window-list (selected-frame))) + (let ((score + (rdebug-display-source-window-categorize win))) + (if (> score candidate-score) + (progn + (setq candidate win) + (setq candidate-score score))))) + candidate))) + +(defun rdebug-frame-source-buffer (frame) + "Return the buffer corresponding to the source file given in FRAME, or nil if none." + (and frame + gud-comint-buffer + (save-current-buffer + (set-buffer gud-comint-buffer) + (gud-find-file (car frame))))) + + +(defun rdebug-current-source-buffer () + "Return the latest source buffer, or nil." + (or (rdebug-frame-source-buffer gud-last-frame) + (rdebug-frame-source-buffer gud-last-last-frame))) + + +(defun rdebug-display-source-buffer () + "Display the current source buffer." + (interactive) + (rdebug-debug-enter "rdebug-display-source-buffer" + (let ((buffer (rdebug-current-source-buffer)) + (last-buffer (rdebug-frame-source-buffer gud-last-last-frame))) + (if buffer + (let ((window + (or + ;; Buffer is already visible, re-use the window. + (get-buffer-window buffer) + ;; Re-use the last window + (and last-buffer + (get-buffer-window last-buffer)) + ;; Find a non-rdebug window. + (rdebug-display-pick-source-window)))) + (select-window window) + (switch-to-buffer buffer)))))) + + +(defun rdebug-pick-source-window () + "Display the source file, but do not switch window." + (save-selected-window + (rdebug-display-source-buffer))) + + +(defun rdebug-display-source-buffer-resync () + "Resync output and display the source buffer." + (interactive) + (call-interactively 'gud-source-resync) + (rdebug-display-source-buffer)) + + +(defun rdebug-delete-frame-or-window () + "Delete frame if there is only one window. Otherwise delete the window." + (interactive) + (if (one-window-p) (delete-frame) + (delete-window))) + +(defun rdebug-goto-entry-try (str) + "See if thre is an entry with number STR. If not return nil." + (goto-char (point-min)) + (if (re-search-forward (concat "^[^0-9]*\\(" str "\\)[^0-9]") nil t) + (progn + (goto-char (match-end 1)) + t) + nil)) + + +;; The following is split in two to facilitate debugging. +(defun rdebug-goto-entry-n-internal (keys) + (if (and (stringp keys) + (= (length keys) 1)) + (progn + (setq rdebug-goto-entry-acc (concat rdebug-goto-entry-acc keys)) + ;; Try to find the longest suffix. + (let ((acc rdebug-goto-entry-acc) + (p (point))) + (while (not (string= acc "")) + (if (not (rdebug-goto-entry-try acc)) + (setq acc (substring acc 1)) + (setq p (point)) + ;; Break loop. + (setq acc ""))) + (goto-char p))) + (message "`rdebug-goto-entry-n' must be bound to a number key"))) + + +(defun rdebug-goto-entry-n () + "Go to an entry number. + +Breakpoints, Display expressions and Stack Frames all have +numbers associated with them which are distinct from line +numbers. In a secondary buffer, this function is usually bound to +a numeric key which will position you at that entry number. To +go to an entry above 9, just keep entering the number. For +example, if you press 1 and then 9, you should jump to entry +1 (if it exists) and then 19 (if that exists). Entering any +non-digit will start entry number from the beginning again." + (interactive) + (if (not (eq last-command 'rdebug-goto-entry-n)) + (setq rdebug-goto-entry-acc "")) + (rdebug-goto-entry-n-internal (this-command-keys))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-secondary) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-secondary.el ends here diff --git a/emacs/rdebug-shortkey.el b/emacs/rdebug-shortkey.el new file mode 100644 index 0000000..10e1710 --- /dev/null +++ b/emacs/rdebug-shortkey.el @@ -0,0 +1,175 @@ +;;; rdebug-watch.el --- Ruby debugger (short and simple) key bindings +;;; and minor mode. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-shortkey.el 807 2008-04-08 19:55:37Z andersl $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file contains code which add short simple key bindings to buffers +;; which are part of an part of an rdebug session. It also handles +;; minor mode setting of these buffers. + +;;; Code: +;; ------------------------------------------------------------------- +;; Source short key mode. +;; +;; When this minor mode is active and the debugger is running, the +;; source window displaying the current debugger frame is marked as +;; read-only and the short keys of the secondary windows can be used, +;; for example, you can use the space-bar to single-step the program. + +;; Implementation note: +;; +;; This is presented to the user as one global minor mode. However, +;; under the surface the real work is done by another, non-global, +;; minor mode named "local short key mode". This is activated and +;; deactivated appropriately by the Rdebug filter functions. + +;; Implementation note: This is the user-level command. It only +;; controls if `rdebug-internal-short-key-mode' should be activated or +;; not. + +(require 'rdebug-source) + +(define-minor-mode rdebug-short-key-mode + "When enabled, short keys can be used in source buffers in `rdebug'." + :group 'rdebug + :global t + :init-value nil + ;; Unless the debugger is running, activating this doesn't do + ;; anything. + (if (featurep 'rdebug-core) + (with-no-warnings + (rdebug-short-key-mode-maybe-activate)))) + +(defvar rdebug-internal-short-key-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "b" 'gud-break) + (define-key map "t" 'rdebug-toggle-source-breakpoint-enabled) + (define-key map [insert] 'rdebug-short-key-mode) + ;;(define-key map "p" 'gud-print) + (rdebug-populate-secondary-buffer-map-plain map) + map) + "Keymap used in `rdebug-internal-short-key-mode'.") + +(defvar rdebug-original-read-only nil + "The value `buffer-read-only' should be restored to after short key mode.") + +;; `define-minor-mode' does not set if the mode was on or off prior to being called. +(defvar rdebug-internal-short-key-mode-previous-state nil + "Used to determine when 'rdebug-internal-short-key-mode' changed state.") + +;; Implementation note: This is the mode that does all the work, it's +;; local to the buffer that is affected. +(define-minor-mode rdebug-internal-short-key-mode + "Minor mode with short keys for source buffers for the `rdebug' debugger. +The buffer is read-only when the minor mode is active. + +Note that this is for internal use only, please use the global +mode `rdebug-short-key-mode'. + +\\{rdebug-internal-short-key-mode-map}" + :group 'rdebug + :global nil + :init-value nil + :lighter " ShortKeys" + :keymap rdebug-internal-short-key-mode-map + (make-local-variable 'rdebug-original-read-only) + (make-local-variable 'rdebug-internal-short-key-mode-previous-state) + ;; Ensure action only is performed when the state actually is toggled. + (unless (eq rdebug-internal-short-key-mode-previous-state + rdebug-internal-short-key-mode) + (if rdebug-internal-short-key-mode + ;; Mode is being turned on. + (progn + (setq rdebug-original-read-only buffer-read-only) + (setq buffer-read-only t)) + ;; Mode is being turned off. + (setq buffer-read-only rdebug-original-read-only)) + ;; Save the current state, so we can determine when the state is + ;; toggled in the future. + (setq rdebug-internal-short-key-mode-previous-state + rdebug-internal-short-key-mode))) + +(defun rdebug-buffer-killed-p (buffer) + "Return t if BUFFER is killed." + (not (buffer-name buffer))) + +(defun rdebug-internal-short-key-mode-on () + "Turn on `rdebug-internal-short-key-mode' in the current debugger frame." + (rdebug-debug-enter "rdebug-internal-short-key-mode-on" + (save-current-buffer + (if (and gud-comint-buffer + (not (rdebug-buffer-killed-p gud-comint-buffer))) + (set-buffer gud-comint-buffer)) + (let ((frame (or gud-last-frame + gud-last-last-frame))) + (if (and frame + rdebug-short-key-mode) + (ignore-errors + ;; `gud-find-file' calls `error' if it doesn't find the file. + (let ((buffer (gud-find-file (car frame)))) + (save-current-buffer + (set-buffer buffer) + ;; Make gud-comint-buffer local + (if gud-comint-buffer + (make-local-variable 'gud-comint-buffer)) + (rdebug-internal-short-key-mode 1))))))))) + + +(defun rdebug-turn-on-short-key-mode () + "Turn on `rdebug-short-key-mode'. + +This function is designed to be used in a user hook, for example: + + (add-hook 'rdebug-mode-hook 'rdebug-turn-on-short-key-mode)" + (interactive) + (rdebug-short-key-mode 1)) + + +(defun rdebug-turn-off-short-key-mode () + "Turn off `rdebug-short-key-mode'." + (interactive) + (rdebug-short-key-mode -1)) + + +(defun rdebug-short-key-mode-maybe-activate () + (if rdebug-short-key-mode + (rdebug-internal-short-key-mode-on) + (rdebug-internal-short-key-mode-off))) + + +(defun rdebug-internal-short-key-mode-off () + "Turn off `rdebug-internal-short-key-mode' in all buffers." + (rdebug-debug-enter "rdebug-internal-short-key-mode-off" + (save-current-buffer + (dolist (buf (buffer-list)) + (set-buffer buf) + (when rdebug-internal-short-key-mode + (rdebug-internal-short-key-mode -1)))))) + +(provide 'rdebug-shortkey) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-shortkey.el ends here diff --git a/emacs/rdebug-source.el b/emacs/rdebug-source.el new file mode 100644 index 0000000..a2bc2cd --- /dev/null +++ b/emacs/rdebug-source.el @@ -0,0 +1,568 @@ +;;; rdebug-source.el --- Ruby debugger user interface. + +;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id: rdebug-source.el 821 2008-04-25 02:54:44Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; This file is loaded when a Ruby source buffer is loaded. It +;; contains, among else, the Debugger menu. + +;;; Code: + +;; ------------------------------------------------------------------- +;; Consistency checks. +;; + +(if (< emacs-major-version 22) + (error + "Rdebug needs at least Emacs 22 or greater - you have version %d." + emacs-major-version)) + + +;; ------------------------------------------------------------------- +;; Dependencies. +;; + +(require 'cl) + +(require 'gud) ; For gud-key-prefix, sigh... +(require 'rdebug) +(require 'rdebug-vars) + + +;; ------------------------------------------------------------------- +;; Key bindings +;; + +(defun rdebug-populate-common-keys-standard (map) + "Bind the basic debugger key layout used by many debuggers. + +\\{rdebug-example-map-standard}" + (define-key map [f5] 'gud-cont) + (define-key map [S-f5] 'rdebug-quit) + (define-key map [f9] 'rdebug-toggle-source-breakpoint) + (define-key map [C-f9] 'rdebug-toggle-source-breakpoint-enabled) + (define-key map [f10] 'rdebug-next) + (define-key map [f11] 'rdebug-step) + (define-key map [S-f11] 'gud-finish)) + + +;; TODO: Verify and complement. +(defun rdebug-populate-common-keys-eclipse (map) + "Bind the basic debugger key layout used by Eclipse. + +\\{rdebug-example-map-eclipse}" + ;;(define-key map [] 'gud-cont) + ;;(define-key map [] 'rdebug-quit) + (define-key map [S-C-b] 'rdebug-toggle-source-breakpoint) + (define-key map [f6] 'rdebug-next) + (define-key map [f5] 'rdebug-step) + (define-key map [f7] 'gud-finish)) + + +;; TODO: Verify and complement. +(defun rdebug-populate-common-keys-netbeans (map) + "Bind the basic debugger key layout used by NetBeans. + +\\{rdebug-example-map-netbeans}" + ;;(define-key map [] 'gud-cont) + ;;(define-key map [] 'rdebug-quit) + ;; F4 - Run to cursor. + (define-key map [S-f8] 'rdebug-toggle-source-breakpoint) + (define-key map [f8] 'rdebug-next) + (define-key map [f7] 'rdebug-step) + (define-key map [M-S-f7] 'gud-finish)) + + +;; Note: This is only used in doc-strings. +(defvar rdebug-example-map-standard + (let ((map (make-sparse-keymap))) + (rdebug-populate-common-keys-standard map) + map) + "Rdebug Standard common keymap used only in doc-string.") + + +(defvar rdebug-example-map-eclipse + (let ((map (make-sparse-keymap))) + (rdebug-populate-common-keys-eclipse map) + map) + "Rdebug Eclipse compatibility common keymap used only in doc-string.") + + +(defvar rdebug-example-map-netbeans + (let ((map (make-sparse-keymap))) + (rdebug-populate-common-keys-netbeans map) + map) + "Rdebug NetBeans compatibility common keymap used only in doc-string.") + + +(defun rdebug-populate-common-keys (map) + "Define the keys that are used by all debugger windows, even by the source. + +The variable `rdebug-populate-common-keys-function' controls the layout." + (define-key map "\C-x\C-a\C-q" 'rdebug-short-key-mode) + (if rdebug-populate-common-keys-function + (funcall rdebug-populate-common-keys-function map))) + + +(defun rdebug-populate-digit-keys (map) + (define-key map "0" 'rdebug-goto-entry-n) + (define-key map "1" 'rdebug-goto-entry-n) + (define-key map "2" 'rdebug-goto-entry-n) + (define-key map "3" 'rdebug-goto-entry-n) + (define-key map "4" 'rdebug-goto-entry-n) + (define-key map "5" 'rdebug-goto-entry-n) + (define-key map "6" 'rdebug-goto-entry-n) + (define-key map "7" 'rdebug-goto-entry-n) + (define-key map "8" 'rdebug-goto-entry-n) + (define-key map "9" 'rdebug-goto-entry-n)) + + +;; ------------------------------------------------------------------- +;; Menu support. +;; + + +;; Note: We want the key binding to show in the menu. However, our +;; situation is a little bit complex: +;; +;; 1) We want the binding of the `common' man (i.e. the function key +;; the user has selected.) +;; +;; 2) We want this even when the menu is disabled and the key isn't +;; bound, typically when the debugger isn't running. +;; +;; This has been solved by setting up an explicit ":keys" properly. +(defun rdebug-menu-item (common-map name cmd &rest args) + "Return a menu item entry with the correct key bindings. + +A command can be bound to a number of different key sequences. If +the rdebug common map contains a binding it is displayed in the +menu. (The common map typically contains function key bindings.)" + (let ((key-binding (where-is-internal cmd (list common-map) t)) + (hint '())) + (if key-binding + (setq hint (list :keys (key-description key-binding)))) + (append (list 'menu-item name cmd) + hint + args))) + + +;; Note, we re-populate the menus of the different minor and major +;; modes. The reason is that Emacs caches the key bindings, which +;; means that wrong ones are shown when buffers are changed. + +;; Remember, all menu items are added in the reverse order! + +(defun rdebug-populate-debugger-menu (map) + "Populate the Rdebug 'Debugger' menu." + (let ((menu (make-sparse-keymap)) + (common-map (make-sparse-keymap))) + ;; Use a simple common map to find the best key sequence to + ;; display in menu. + (rdebug-populate-common-keys common-map) + + (define-key map [menu-bar debugger] (cons "Debugger" menu)) + + (define-key menu [break-delete] + (rdebug-menu-item common-map "Enable/disable breakpoint" + 'rdebug-toggle-source-breakpoint-enabled + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [break] + (rdebug-menu-item common-map "Toggle breakpoint" + 'rdebug-toggle-source-breakpoint + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [finish] + (rdebug-menu-item common-map "Step out" 'gud-finish + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [step] + (rdebug-menu-item common-map "Step into" 'rdebug-step + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [next] + (rdebug-menu-item common-map "Step over" 'rdebug-next + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [cont] + (rdebug-menu-item common-map "Continue" 'rdebug-continue + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger line1] '(menu-item "--")) + + (define-key menu [stop] + (rdebug-menu-item + common-map "Stop the debugger" 'rdebug-quit + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key menu [start] + (rdebug-menu-item common-map "Start the debugger" 'rdebug)) + + (define-key map [menu-bar debugger line2] '(menu-item "--")) + + ;; -------------------- + ;; The "Options" submenu. + + (let ((submenu (make-sparse-keymap))) + (define-key menu [options] (cons "Options" submenu))) + + (define-key map [menu-bar debugger options customize] + (rdebug-menu-item common-map + "Customize Rdebug" 'rdebug-customize)) + + (define-key map [menu-bar debugger options line1] '(menu-item "--")) + + + + ;; ---------------- + ;; The "short key" toggle. + + (define-key map [menu-bar debugger options short-key-mode] + (rdebug-menu-item common-map + "Short keys in source" 'rdebug-short-key-mode + :button + '(:toggle + . rdebug-short-key-mode))) + + (define-key map [menu-bar debugger options line2] '(menu-item "--")) + + ;; ---------------- + ;; Separate I/O buffer. + + (define-key map [menu-bar debugger options io-buffer] + (rdebug-menu-item common-map + "Separate I/O buffer" + 'rdebug-toggle-use-separate-io-buffer + :button + '(:toggle + . rdebug-use-separate-io-buffer))) + + ;; -------------------- + ;; The optional secondary windows submenu. + + + ;; Placeholder used when populating the menu of the secondary buffers. + (define-key menu [placeholder] nil) + + ;; -------------------- + ;; The "Window Layout" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key menu [layout] (cons "Window Layout" submenu))) + + ;; ---------------- + ;; The "Window Layout" submenu. + + + ;; TODO: The following is a somewhat clumsy implementation. Maybe we can + ;; automatically generate the entries, or use the `dynamic' menu kind? + ;; + ;; Also, there might be other situations where the list might be + ;; handy, e.g. completion. + (let ((predefined '(rdebug-window-layout-standard + rdebug-window-layout-no-shell + rdebug-window-layout-conservative + rdebug-window-layout-stack-of-windows + rdebug-window-layout-rocky + rdebug-window-layout-rocky2))) + + (define-key map [menu-bar debugger layout other] + (rdebug-menu-item + common-map + "Other" + 'rdebug-set-window-layout + :button + `(:radio + . (not (memq rdebug-window-layout-function (quote ,predefined)))))) + + (define-key map [menu-bar debugger layout rocky] + (rdebug-menu-item + common-map + "Rocky's Own" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-rocky)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-rocky)))) + + (define-key map [menu-bar debugger layout rocky2] + (rdebug-menu-item + common-map + "Rocky II" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-rocky2)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-rocky2)))) + + (define-key map [menu-bar debugger layout stack] + (rdebug-menu-item + common-map + "Stack of Windows" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-stack-of-windows)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-stack-of-windows)))) + + (define-key map [menu-bar debugger layout conservative] + (rdebug-menu-item + common-map + "Conservative" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-conservative)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-conservative)))) + + (define-key map [menu-bar debugger layout no-shell] + (rdebug-menu-item + common-map + "No Shell" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-no-shell)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-no-shell)))) + + (define-key map [menu-bar debugger layout standard] + (rdebug-menu-item + common-map + "Standard" + (lambda () + (interactive) + (rdebug-set-window-layout 'rdebug-window-layout-standard)) + :button + '(:radio + . (eq rdebug-window-layout-function + 'rdebug-window-layout-standard))))) + + (define-key map [menu-bar debugger layout line3] '(menu-item "--")) + + (define-key map [menu-bar debugger layout initial] + (rdebug-menu-item common-map + "Restore Debugger Layout" + 'rdebug-restore-debugger-window-layout + :enable '(fboundp 'rdebug-restore-debugger-window-layout))) + + (define-key map [menu-bar debugger layout line1] '(menu-item "--")) + + ;; Note: It seems as though :enable doesn't work when :button is used. + (define-key map [menu-bar debugger layout debugger] + (rdebug-menu-item common-map "Current Debugger Layout" + 'rdebug-display-debugger-window-configuration + :button + '(:radio + . (eq rdebug-window-configuration-state 'debugger)))) + + (define-key map [menu-bar debugger layout original] + (rdebug-menu-item common-map "Original Layout" + 'rdebug-display-original-window-configuration + :button + '(:radio + . (eq rdebug-window-configuration-state 'original)))) + + ;; -------------------- + ;; The "View" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key menu [view] (cons "View" submenu))) + + (define-key map [menu-bar debugger view output] + (rdebug-menu-item common-map "Output" 'rdebug-display-output-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view watch] + (rdebug-menu-item common-map "Watch" 'rdebug-display-watch-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view stack] + (rdebug-menu-item common-map "Stack-Frame trace" + 'rdebug-display-frame-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view shell] + (rdebug-menu-item common-map "Debugger Shell" 'rdebug-display-cmd-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view variables] + (rdebug-menu-item common-map "Variables" 'rdebug-display-variables-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view breakpoints] + (rdebug-menu-item common-map + "Breakpoints" 'rdebug-display-breakpoints-buffer + :enable '(get-buffer-process gud-comint-buffer))) + + (define-key map [menu-bar debugger view source] + (rdebug-menu-item common-map + "Source" 'rdebug-display-source-buffer + :enable '(get-buffer-process gud-comint-buffer))) + menu)) + + +;; ----------------------------------------------- +;; Key bindings and menu for secondary buffers. +;; + +(defun rdebug-populate-secondary-buffer-map-plain (map) + "Bind the plain keys used in rdebug secondary buffers. + +This does not menus or prefix keys." + ;; Keys to view other buffers. + (let ((prefix-map (make-sparse-keymap))) + (define-key map "?" 'rdebug-display-secondary-window-help-buffer) + (define-key map "B" 'rdebug-display-breakpoints-buffer) + (define-key map "C" 'rdebug-display-cmd-buffer) + (define-key map "E" 'rdebug-display-error-buffer) + (define-key map "F" 'rdebug-display-frame-buffer) + (define-key map "I" 'rdebug-display-info-buffer) + (define-key map "O" 'rdebug-display-output-buffer) + (define-key map "S" 'rdebug-display-source-buffer) + (define-key map "V" 'rdebug-display-variables-buffer) + (define-key map "W" 'rdebug-display-watch-buffer) + ;; Common debugger commands. + (define-key map " " 'rdebug-step) + (define-key map "_" 'rdebug-set-stepping-prefix) + (define-key map "+" 'rdebug-set-stepping-prefix) + (define-key map "-" 'rdebug-set-stepping-prefix) + (define-key map "<" 'rdebug-newer-frame) + (define-key map ">" 'rdebug-older-frame) + ;; (define-key map "a" 'gud-args) + ;; (define-key map "b" 'gud-break) + (define-key map "c" 'rdebug-continue) + ;; (define-key map "d" 'gud-remove) + (define-key map "f" 'gud-finish) + (define-key map "n" 'rdebug-next) + (define-key map "p" prefix-map) + (define-key map "q" 'rdebug-quit) + (define-key map "r" 'rdebug-restart) + (define-key map "R" 'rdebug-restart) + (define-key map "s" 'rdebug-step) + (define-key map [M-down] 'rdebug-locring-newer) + (define-key map [M-up] 'rdebug-locring-older) + (define-key map [M-S-down] 'rdebug-locring-newest) + (define-key map [M-S-up] 'rdebug-locring-oldest) + (define-key map [mouse-3] 'rdebug-variables-pretty-print-mouse) + (define-key prefix-map "l" 'rdebug-print-list-region) + (define-key prefix-map "p" 'rdebug-pretty-print-region) + (define-key prefix-map "s" 'rdebug-print-sorted-region) + )) + + +;; ------------------------------------------------------------------- +;; Window layout. +;; + +;; This function is intended for the Options submenu. +(defun rdebug-set-window-layout (func) + "Set and, if the debugger is running, display the window layout." + (interactive "aWindow layout function: ") + (setq rdebug-window-layout-function func) + (if gud-comint-buffer + (with-no-warnings + (rdebug-setup-windows)))) + + +;; ------------------------------------------------------------------- +;; The source buffer rdebug support mode. +;; +;; This is a minor mode that is active in Ruby source buffers. It +;; provides the menu and, when the debugger is active, the debugger +;; key bindings. + +(defvar rdebug-debugger-support-minor-mode-map-when-deactive + (let ((map (make-sparse-keymap)) + (prefix-map (make-sparse-keymap))) + (rdebug-populate-debugger-menu map) + (rdebug-populate-secondary-buffer-map-plain prefix-map) + (define-key map gud-key-prefix prefix-map) + map) + "Keymap used by rdebugs support minor mode when the debugger is active.") + +(defvar rdebug-debugger-support-minor-mode-map-when-active + (let ((map (make-sparse-keymap)) + (prefix-map (make-sparse-keymap))) + (rdebug-populate-debugger-menu map) + (rdebug-populate-secondary-buffer-map-plain prefix-map) + (define-key prefix-map [insert] 'rdebug-short-key-mode) + (define-key map gud-key-prefix prefix-map) + (rdebug-populate-common-keys map) + map) + "Keymap used by rdebugs support minor mode when the debugger not active.") + + +(define-minor-mode rdebug-debugger-support-minor-mode + "Minor mode active in source buffers that use the `rdebug' Ruby debugger." + :group rdebug + :global nil + :init-value nil + :keymap rdebug-debugger-support-minor-mode-map-when-deactive + (setq mode-line-process (and rdebug-debugger-support-minor-mode + 'rdebug-mode-line-process))) + + +;;;###autoload +(defun rdebug-turn-on-debugger-support () + "Enable extra source buffer support for the `rdebug' Ruby debugger. + +This includes a 'Debugger' menu and special key bindings when the +debugger is active." + (rdebug-debugger-support-minor-mode 1)) + + +;; ------------------------------------------------------------------- +;; Use separate I/O buffer +;; + +(defun rdebug-toggle-use-separate-io-buffer () + "Toggle `rdebug-use-separate-io-buffer'. +This is used by the menu." + (interactive) + (setq rdebug-use-separate-io-buffer (not rdebug-use-separate-io-buffer)) + (if (interactive-p) + (message "Issue M-x rdebug-restore-debugger-window-layout \ +RET to update display."))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-source) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-source.el ends here diff --git a/emacs/rdebug-track.el b/emacs/rdebug-track.el new file mode 100644 index 0000000..1d9b4e0 --- /dev/null +++ b/emacs/rdebug-track.el @@ -0,0 +1,392 @@ +;;; rdebug-track.el --- Tracking the Ruby debugger from a shell +;; $Id: rdebug-track.el 909 2009-03-11 18:57:08Z rockyb $ + +;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren +;; Modified from python-mode in particular the part: +;; pdbtrack support contributed by Ken Manheimer, April 2001. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; `rdebug-track-mode' allows access to full debugger user interface +;; for Ruby debugger sessions started in a standard shell window. +;; `turn-on-rdebug-track-mode' turns the mode on and +;; `turn-off-rdebug-track-mode' turns it off. +;; +;;; Customization: +;; `rdebug-track' sets whether file tracking is done by the shell prompt. +;; `rdebug-track-minor-mode-string' sets the mode indicator to show that +;; tracking is in effect. +;; + +;;; Code: + +;; ------------------------------------------------------------------- +;; Customizable variables. +;; + +(defgroup rdebug-track nil + "Ruby debug and rdebug file tracking by watching the shell prompt." + :prefix "rdebug-track" + :group 'shell) + +(defcustom rdebug-track-do-tracking-p nil + "*Controls whether the rdebug-track feature is enabled or not. +When non-nil, rdebug-track is enabled in all comint-based buffers, +e.g. shell buffers and the *Ruby* buffer. When using rdebug to debug a +Ruby program, rdebug-track notices the rdebug prompt and displays the +source file and line that the program is stopped at, much the same way +as gud-mode does for debugging C programs with gdb." + :type 'boolean + :group 'rdebug) +(make-variable-buffer-local 'rdebug-track-do-tracking-p) + +(defcustom rdebug-track-minor-mode-string " rdebug" + "*String to use in the minor mode list when rdebug-track is enabled." + :type 'string + :group 'rdebug) + + +;; ------------------------------------------------------------------- +;; Variables. +;; + +(defvar gud-rdebug-history nil + "History of argument lists passed to rdebug.") + +;; rdebug-track constants +(defconst rdebug-track-stack-entry-regexp + "^(\\([-a-zA-Z0-9_/.]*\\):\\([0-9]+\\)):[ \t]?\\(.*\n\\)" + "Regular expression rdebug-track uses to find a stack trace entry.") + +(defconst rdebug-track-track-range 10000 + "Max number of characters from end of buffer to search for stack entry.") + + +;; ------------------------------------------------------------------- +;; Dependencies. +;; + +(require 'comint) +(require 'custom) +(require 'cl) +(require 'compile) +(require 'gud) +(require 'shell) +(require 'rdebug-breaks) +(require 'rdebug-cmd) +(require 'rdebug-core) + + +;; ------------------------------------------------------------------- +;; Rdebug track -- support for attaching the `rdebug' ruby debugger to +;; a process running in a shell buffer. +;; + +(defvar rdebug-track-is-tracking-p t) + +(defun rdebug-track-overlay-arrow (activation) + "Activate or de arrow at beginning-of-line in current buffer." + ;; This was derived/simplified from edebug-overlay-arrow + (cond (activation + (setq overlay-arrow-position (make-marker)) + (setq overlay-arrow-string "=>") + (set-marker overlay-arrow-position (point) (current-buffer)) + (setq rdebug-track-is-tracking-p t)) + (rdebug-track-is-tracking-p + (setq overlay-arrow-position nil) + (setq rdebug-track-is-tracking-p nil)) + )) + +(defun rdebug-track-track-stack-file (text) + "Show the file indicated by the rdebug stack entry line, in a separate window. +Activity is disabled if the buffer-local variable +`rdebug-track-do-tracking-p' is nil. + +We depend on the rdebug input prompt matching `rdebug-input-prompt-regexp' +at the beginning of the line." + ;; Instead of trying to piece things together from partial text + ;; (which can be almost useless depending on Emacs version), we + ;; monitor to the point where we have the next rdebug prompt, and then + ;; check all text from comint-last-input-end to process-mark. + ;; + ;; Also, we're very conservative about clearing the overlay arrow, + ;; to minimize residue. This means, for instance, that executing + ;; other rdebug commands wipe out the highlight. You can always do a + ;; 'where' (aka 'w') command to reveal the overlay arrow. + (rdebug-debug-enter "rdebug-track-track-stack-file" + (let* ((origbuf (current-buffer)) + (currproc (get-buffer-process origbuf))) + + (if (not (and currproc rdebug-track-do-tracking-p)) + (rdebug-track-overlay-arrow nil) + ;;else + (let* ((procmark (process-mark currproc)) + (block-start (max comint-last-input-end + (- procmark rdebug-track-track-range))) + (block-str (buffer-substring block-start procmark)) + target target_fname target_lineno target_buffer) + + (if (not (string-match rdebug-input-prompt-regexp block-str)) + (rdebug-track-overlay-arrow nil) + ;;else + (setq target (rdebug-track-get-source-buffer block-str)) + + (if (stringp target) + (rdebug-debug-message "rdebug-track: %s" target) + ;;else + (gud-rdebug-marker-filter block-str) + (setq target_lineno (car target)) + (setq target_buffer (cadr target)) + (setq target_fname (buffer-file-name target_buffer)) + (setq gud-last-frame (cons target_fname target_lineno)) + (switch-to-buffer-other-window target_buffer) + (goto-line target_lineno) + (rdebug-debug-message "rdebug-track: line %s, file %s" + target_lineno target_fname) + (rdebug-track-overlay-arrow t) + (rdebug-set-frame-top-arrow (current-buffer)) + (set (make-local-variable 'gud-comint-buffer) origbuf) + (set (make-local-variable 'gud-delete-prompt-marker) + (make-marker)) + (pop-to-buffer origbuf t) + (rdebug-locring-add gud-last-frame + rdebug-source-location-ring)) + + ;; Delete processed annotations from buffer. + (save-excursion + (let ((annotate-start) + (annotate-end (point-max))) + (goto-char block-start) + (while (re-search-forward + rdebug-annotation-start-regexp annotate-end t) + (let* ((start (match-beginning 0)) + (end (match-end 0)) + (name (or (match-string 1) "source"))) + (cond ((string= name "prompt\n") + (delete-region (- start 1) end)) + ((string= name "pre-prompt\n") + (delete-region start end)) + ((string= name "error-begin\n") + (delete-region start end)) + ((re-search-forward rdebug-annotation-end-regexp + annotate-end t) + (delete-region start (point))) + (t (forward-line))))))) + )))))) + +(defun rdebug-track-get-source-buffer (block-str) + "Return line and buffer of code indicated by block-str's traceback text. + +We look first to visit the file indicated in the trace. + +Failing that, we look for the most recently visited ruby-mode buffer +with the same name or having having the named function. + +If we're unable find the source code we return a string describing the +problem as best as we can determine." + + (if (not (string-match rdebug-position-regexp block-str)) + "line number cue not found" + ;;else + (let* ((filename (match-string rdebug-marker-regexp-file-group block-str)) + (lineno (string-to-number + (match-string rdebug-marker-regexp-line-group block-str))) + funcbuffer) + + (cond ((file-exists-p filename) + (list lineno (find-file-noselect filename))) + + ((= (elt filename 0) ?\<) + (format "(Non-file source: '%s')" filename)) + + (t (format "Not found: %s" filename)))))) + + + +;; ----------------------------------------------- +;; Rdebug track mode +;; + + +(defcustom rdebug-track-mode-text " rdebug" + "*String to display in the mode line when rdebug-track mode is active. + +\(When the string is not empty, make sure that it has a leading space.)" + :tag "rdebug mode text" ; To separate it from `global-...' + :group 'rdebug + :type 'string) + +(define-minor-mode rdebug-track-mode + "Minor mode for tracking ruby debugging inside a process shell." + :init-value nil + ;; The indicator for the mode line. + :lighter rdebug-track-mode-text + ;; The minor mode bindings. + :global nil + :group 'rdebug + (rdebug-track-toggle-stack-tracking 1) + (setq rdebug-track-is-tracking-p t) + (local-set-key "\C-cg" 'rdebug-goto-traceback-line) + (local-set-key "\C-cG" 'rdebug-goto-dollarbang-traceback-line) + + (add-hook 'comint-output-filter-functions 'rdebug-track-track-stack-file) + (run-mode-hooks 'rdebug-track-mode-hook)) + + +(defun rdebug-track-toggle-stack-tracking (arg) + (interactive "P") + (if (not (get-buffer-process (current-buffer))) + (message "No process associated with buffer '%s'" (current-buffer)) + ;;else + ;; missing or 0 is toggle, >0 turn on, <0 turn off + (if (or (not arg) + (zerop (setq arg (prefix-numeric-value arg)))) + (setq rdebug-track-do-tracking-p (not rdebug-track-do-tracking-p)) + (setq rdebug-track-do-tracking-p (> arg 0))) + (message "%sabled rdebug's rdebug-track" + (if rdebug-track-do-tracking-p "En" "Dis")))) + + +;;;###autoload +(defun turn-on-rdebug-track-mode () + "Turn on rdebug-track mode. + +This function is designed to be added to hooks, for example: + (add-hook 'comint-mode-hook 'turn-on-rdebug-track-mode)" + (interactive) + (set (make-local-variable 'gud-last-last-frame) nil) + (set (make-local-variable 'gud-last-frame) nil) + (set (make-local-variable 'gud-comint-buffer) (current-buffer)) + + (set (make-local-variable 'gud-marker-filter) 'gud-rdebug-marker-filter) + (set (make-local-variable 'gud-minor-mode) 'rdebug) + (set (make-local-variable 'comint-prompt-regexp) (concat "^" rdebug-input-prompt-regexp)) + + (set (make-local-variable 'gud-find-file) 'gud-rdebug-find-file) + + (rdebug-command-initialization) + + (rdebug-track-mode 1)) + + +(defun turn-off-rdebug-track-mode () + "Turn off rdebug-track mode." + (interactive) + (setq rdebug-track-is-tracking-p nil) + + (rdebug-track-toggle-stack-tracking 0) + (if (local-variable-p 'gud-last-frame) + (setq gud-last-frame nil)) + (while (not (ring-empty-p rdebug-source-location-ring)) + (ring-remove rdebug-source-location-ring)) + (remove-hook 'comint-output-filter-functions + 'rdebug-track-track-stack-file)) + + +;; ----------------------------------------------- +;; The `attach' function. +;; + +(defun rdebug-track-attach (&optional name rename-shell) + "Do things to make the current process buffer work like a +rdebug command buffer. In particular, the buffer is renamed, +gud-mode is set, and rdebug-track-mode is turned on, among other +things. When `rdebug-many-windows' is non-nil, the initial debugger +window layout is used." + (interactive "sProgram name: ") + (rdebug-debug-enter "rdebug-set-windows" + (rdebug-set-window-configuration-state 'debugger t) + + ;; from rdebug-common-init + (gud-mode) + (set (make-local-variable 'gud-marker-filter) 'gud-rdebug-marker-filter) + (set (make-local-variable 'gud-minor-mode) 'rdebug) + (set (make-local-variable 'gud-last-frame) nil) + (set (make-local-variable 'gud-last-last-frame) nil) + + (set (make-local-variable 'gud-find-file) 'gud-rdebug-find-file) + (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter) + (gud-set-buffer) + ;; + + (rdebug-track-mode 1) + (rdebug-command-initialization) + + (when name + (if rename-shell + (rename-buffer (format "*rdebug-cmd-%s*" gud-target-name))) + (setq gud-target-name name) + (setq gud-comint-buffer (current-buffer))) + + ;; Setup exit callback so that the original frame configuration + ;; can be restored. + (let ((process (get-buffer-process gud-comint-buffer))) + (when process + (unless (equal rdebug-line-width 120) + (gud-call (format "set width %d" rdebug-line-width))) + (set-process-sentinel process + 'rdebug-process-sentinel))) + + (when gud-last-frame + (setq gud-last-last-frame gud-last-frame)) + + ;; Add the buffer-displaying commands to the Gud buffer, + ;; FIXME: combine with code in rdebug-track.el; make common + ;; command buffer mode map. + (let ((prefix-map (make-sparse-keymap)) + (map (current-local-map))) + (define-key map [M-down] 'rdebug-locring-newer) + (define-key map [M-up] 'rdebug-locring-older) + (define-key map [M-S-down] 'rdebug-locring-newest) + (define-key map [M-S-up] 'rdebug-locring-oldest) + (define-key map gud-key-prefix prefix-map) + (define-key prefix-map "t" 'rdebug-goto-traceback-line) + (define-key prefix-map "!" 'rdebug-goto-dollarbang-traceback-line) + + (rdebug-populate-secondary-buffer-map-plain prefix-map)) + + (rdebug-populate-common-keys (current-local-map)) + (rdebug-populate-debugger-menu (current-local-map)) + + (set (make-local-variable 'comint-prompt-regexp) (concat "^" rdebug-input-prompt-regexp)) + (setq paragraph-start comint-prompt-regexp) + + (setcdr (assq 'rdebug-debugger-support-minor-mode minor-mode-map-alist) + rdebug-debugger-support-minor-mode-map-when-active) + + (gud-call "set annotate 3") + (gud-call "frame 0") + (when rdebug-many-windows + (rdebug-setup-windows)) + (run-hooks 'rdebug-mode-hook))) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-track) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-track.el ends here diff --git a/emacs/rdebug-varbuf.el b/emacs/rdebug-varbuf.el new file mode 100644 index 0000000..4ece36b --- /dev/null +++ b/emacs/rdebug-varbuf.el @@ -0,0 +1,150 @@ +;;; rdebug-varbuf.el --- This file contains code dealing with the Ruby +;;; debugger's "variables" secondary buffer. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-varbuf.el 711 2008-02-20 07:09:17Z andersl $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;;; Code: + +(defvar rdebug-variables-mode-map + (let ((map (make-sparse-keymap))) + (suppress-keymap map) + (define-key map "\r" 'rdebug-variables-edit) + ;; (define-key map "e" 'rdebug-edit-variables-value) + (define-key map [mouse-2] 'rdebug-variables-edit-mouse) + (define-key map "e" 'rdebug-variables-print) + (define-key map "x" 'rdebug-variables-pretty-print) + (rdebug-populate-secondary-buffer-map map) + + ;; -------------------- + ;; The "Variables window" submenu. + + (let ((submenu (make-sparse-keymap))) + (define-key-after map [menu-bar debugger variables] + (cons "Variables window" submenu) + 'placeholder)) + + (define-key map [menu-bar debugger variables edit] + '(menu-item "Edit" rdebug-variables-edit + :enable (eq major-mode 'rdebug-variables-mode))) + + map) + "Keymap used in the variables buffer in the `rdebug' Ruby debugger.") + +(defvar rdebug-variables-font-lock-keywords + '(("@[a-zA-Z0-9_]+" 0 font-lock-variable-name-face) + ("\\<\\(nil\\|true\\|false\\)\\>" 0 font-lock-constant-face) + ("#<\\([a-zA-Z0-9_]+\\):\\([0-9a-fx]*\\)" + (1 font-lock-type-face) + (2 font-lock-constant-face))) + "Font-lock rules for the variables and watch windows in `rdebug'.") + +(defun rdebug-display-variables-buffer () + "Display the rdebug variables buffer." + (interactive) + (rdebug-display-secondary-buffer "variables")) + +(defun rdebug-variables-mode () + "Major mode for the variables buffer in the `rdebug' Ruby debugger. + +\\{rdebug-variables-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-variables-mode) + (setq mode-name "RDEBUG Variables") + (setq buffer-read-only t) + (setq truncate-lines t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (set (make-local-variable 'font-lock-defaults) + '(rdebug-variables-font-lock-keywords)) + (use-local-map rdebug-variables-mode-map) + (run-mode-hooks 'rdebug-variables-mode-hook)) + +(defun rdebug-setup-variables-buffer (buf comint-buffer) + (rdebug-debug-enter "rdebug-setup-variables-buffer" + (with-current-buffer buf + (rdebug-variables-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer)))) + +(defun rdebug-variables-edit-mouse (&optional event) + "Assign a value to a variable displayed in the variables buffer. +This function is intended to be bound to a mouse key" + (interactive (list last-input-event)) + (save-excursion + (if event (posn-set-point (event-end event))) + (call-interactively 'rdebug-variables-edit))) + +(defun rdebug-variables-edit (var value) + "Assign a value to a variable displayed in the variables buffer." + (interactive + (let ((var nil) + (value nil)) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\(@?[a-zA-Z_0-9]+\\) *= *\\(.*\\)$") + (setq var (match-string 1)) + (setq value (match-string 2)) + (setq value (read-from-minibuffer + (format "New value (%s): " var) value))) + (list var value)))) + (gud-call (format "p %s=%s" var value))) + +(defun rdebug-variables-pretty-print (var) + "Pretty print a variable in the variables buffer." + (interactive + (let ((var nil)) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\(@?[a-zA-Z_0-9]+\\) *= *\\(.*\\)$") + (setq var (match-string 1))) + (list var)))) + (rdebug-print-cmd var "pp")) + +(defun rdebug-variables-pretty-print-mouse (&optional event) + "Assign a value to a variable displayed in the variables buffer. +This function is intended to be bound to a mouse key" + (interactive (list last-input-event)) + (save-excursion + (if event (posn-set-point (event-end event))) + (call-interactively 'rdebug-variables-pretty-print))) + +(defun rdebug-variables-print (var) + "Print a variable in the variables buffer." + (interactive + (let ((var nil)) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\(@?[a-zA-Z_0-9]+\\) *= *\\(.*\\)$") + (setq var (match-string 1))) + (list var)))) + (rdebug-print-cmd var "p")) + +(provide 'rdebug-varbuf) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-varbuf.el ends here diff --git a/emacs/rdebug-vars.el b/emacs/rdebug-vars.el new file mode 100644 index 0000000..6137095 --- /dev/null +++ b/emacs/rdebug-vars.el @@ -0,0 +1,125 @@ +;;; rdebug-var.el --- Ruby debugger variables (other than regexps) + +;; Copyright (C) 2007 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007 Anders Lindgren + +;; $Id: rdebug-vars.el 769 2008-03-17 14:29:40Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; See the manual and the file `rdebug.el' for more information. + +;; +;; Introduction: +;; +;; This is a full-blown debugger user interface to the Ruby rdebug +;; debugger shell. +;; +;; Internal debug support. When `rdebug-debug-active' is non-nil, +;; internal debug messages are placed in the buffer *Xrdebug*. +;; Functions can be annotated with `rdebug-debug-enter' to display a +;; call trace. +;; + +;;; Code: + +(defvar rdebug-current-line-number 1 + "The line number in a secondary window that you were in. We need to save + this value because secondary windows get recreated a lot") + +(defvar rdebug-debug-active nil + "Non-nil when rdebug should emit internal debug output to *Xrdebug*.") + +;; Indentation depth of `rdebug-debug-enter'. +(defvar rdebug-debug-depth 0) + +(defvar rdebug-debugger-window-configuration nil + "The saved window layout of the debugger.") + +(defvar rdebug-frames-current-frame-number nil + "The frame number of the selected frame.") + +(defvar rdebug-goto-entry-acc "") + +(defvar rdebug-output-marker-number 0 + "Number to be used when `rdebug-output-add-divider' is next + called on the secondary output buffer.") + +(defvar rdebug-original-window-configuration nil + "The window layout rdebug should restore when the debugger exits.") + +;; Terminology: a "secondary buffer" is the physical emacs buffer, +;; which can be visible or invisible. A "secondary window", is a window +;; that rdebug is reusing to display different secondary buffers. +;; +;; For example, the "secondary-window-help" buffer is named the way it +;; is since it gives help on how the secondary window is used. +(defvar rdebug-secondary-buffer nil + "Non-nil for rdebug secondary buffers (e.g. the breakpoints buffer).") + +;; Currently, this is the "output" and "info" buffers. +(defvar rdebug-accumulative-buffer nil + "Non-nil for Rdebug secondary buffers that grow.") + +;; This is used to ensure that the original frame configuration is +;; restored even when the user re-starts the debugger several times. +(defvar rdebug-window-configuration-state 'original + "Represent the window layout that currently is in use. +Can be `original' or `debugger'.") + +;; FIXME instead of just a list of commands it should a list of pairs +;; command and lambda callback routine to call with the shell output. +(defvar rdebug-call-queue '() + "List of commands queued up for results of a `rdebug-call'. + +Each entry is a list of the following form: + + (name ... options ...) + +Name is the actual command string. Options are zero or more tags +describing what should happen with the output. + +This is buffer local variable to the rdebug shell buffer.") + +;; TODO: Make this buffer-local to the shell buffer. +(defvar rdebug-inferior-status nil + "The status of the Ruby program debugged under RDebug.") + +;; Unlike the gdb implementation, we don't have to actively update the +;; mode line. +(defvar rdebug-mode-line-process + '(:eval + (and (fboundp 'rdebug-display-inferior-status) + (rdebug-display-inferior-status))) + "A string representing the current debugger state, or nil. +The mode line is displayed in all source and secondary buffers.") +;; Needed to get :eval to work. +(put 'rdebug-mode-line-process 'risky-local-variable t) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug-vars) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-vars.el ends here diff --git a/emacs/rdebug-watch.el b/emacs/rdebug-watch.el new file mode 100644 index 0000000..1a50deb --- /dev/null +++ b/emacs/rdebug-watch.el @@ -0,0 +1,132 @@ +;;; rdebug-watch.el --- This file contains code dealing with the Ruby +;;; debugger's watch (AKA display) secondary buffer. + +;; Copyright (C) 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2008 Anders Lindgren + +;; $Id: rdebug-watch.el 711 2008-02-20 07:09:17Z andersl $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: +;; See the manual and the file `rdebug.el' for more information. + +;;; Code: + +(require 'rdebug-dbg) + +(defvar rdebug-watch-mode-map + (let ((map (make-sparse-keymap))) + (suppress-keymap map) + (define-key map "a" 'rdebug-watch-add) + (define-key map "\C-d" 'rdebug-watch-delete) + (define-key map "d" 'rdebug-watch-delete) + (define-key map "e" 'rdebug-watch-edit) + (define-key map "\r" 'rdebug-watch-edit) + (rdebug-populate-digit-keys map) + (rdebug-populate-secondary-buffer-map map) + + ;; -------------------- + ;; The "Watch window" submenu. + (let ((submenu (make-sparse-keymap))) + (define-key-after map [menu-bar debugger watch] + (cons "Watch window" submenu) + 'placeholder)) + + (define-key map [menu-bar debugger watch delete] + '(menu-item "Delete" rdebug-watch-delete + :enable (eq major-mode 'rdebug-watch-mode))) + (define-key map [menu-bar debugger watch goto] + '(menu-item "Edit" rdebug-watch-edit + :enable (eq major-mode 'rdebug-watch-mode))) + (define-key map [menu-bar debugger watch add] + '(menu-item "Add" rdebug-watch-add)) + + map) + "Keymap used in the watch buffer in the `rdebug' Ruby debugger.") + +(defun rdebug-display-watch-buffer () + "Display the rdebug watch buffer." + (interactive) + (rdebug-display-secondary-buffer "watch")) + +(defun rdebug-watch-mode () + "Major mode for displaying watched expressions in the `rdebug' Ruby debugger. + +\\{rdebug-watch-mode}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'rdebug-watch-mode) + (setq mode-name "RDEBUG Watch") + (setq buffer-read-only t) + (setq truncate-lines t) + (set (make-local-variable 'rdebug-secondary-buffer) t) + (setq mode-line-process 'rdebug-mode-line-process) + (set (make-local-variable 'font-lock-defaults) + '(rdebug-variables-font-lock-keywords)) + (use-local-map rdebug-watch-mode-map) + (run-mode-hooks 'rdebug-watch-mode-hook)) + +(defun rdebug-setup-watch-buffer (buf comint-buffer) + "Set up the rdebug debugger watch secondary buffer. + +This buffer contains display expressions. BUF is the buffer to set up and COMINT-BUFFER be the assocated gud process buffer." + (rdebug-debug-enter "rdebug-setup-watch-buffer" + (with-current-buffer buf + (rdebug-watch-mode) + (set (make-local-variable 'gud-comint-buffer) comint-buffer)))) + +(defun rdebug-watch-add (expr) + "Add EXPR to watch in the `rdebug' Ruby debugger." + (interactive "sRuby expression: ") + (if (not (string= expr "")) + (gud-call (format "display %s" expr)))) + + +(defun rdebug-watch-delete () + "Delete a display expression in the `rdebug' Ruby debugger." + (interactive) + (save-excursion + (beginning-of-line) + (if (looking-at "^\\([0-9]+\\):") + (gud-call (format "undisplay %s" (match-string 1)))))) + +(defun rdebug-watch-edit (number expr) + "Edit a display expression in the `rdebug' Ruby debugger. +Argument NUMBER is the display expression number. +Argument EXPR is the expression for display number NUMBER." + (interactive + (let ((number nil) + (expr nil)) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\([0-9]+\\): *\\([^=]*[^= ]\\) *=") + (setq number (match-string 1)) + (setq expr (match-string 2)) + (setq expr (read-from-minibuffer "Ruby expression: " expr))) + (list number expr)))) + (when expr + (gud-call (format "undisplay %s" number)) + (gud-call (format "display %s" expr)))) + + +(provide 'rdebug-watch) + +;;; Local variables: +;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1) +;;; End: + +;;; rdebug-watch.el ends here diff --git a/emacs/rdebug.el b/emacs/rdebug.el new file mode 100644 index 0000000..2a326a1 --- /dev/null +++ b/emacs/rdebug.el @@ -0,0 +1,326 @@ +;;; rdebug.el --- Ruby debugger user interface, startup file. + +;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org) +;; Copyright (C) 2007, 2008 Anders Lindgren + +;; $Id: rdebug.el 409 2007-12-14 02:36:37Z rockyb $ + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; +;; Introduction: +;; +;; This is a full-blown debugger user interface to the Ruby rdebug +;; debugger shell. +;; +;; The main features are: +;; +;; * Window layout with dedicated windows for: +;; + Local and member variables +;; + Stack trace +;; + Display expressions +;; + Breakpoints +;; + Output +;; + Debugger Shell +;; +;; * Source-level debugging: +;; + The current source file is shown and current line is marked. +;; + Function keys bindings for effective stepping in the source code. +;; + A "Debugger" menu for easy access to all features. +;; +;; * A number of predefined window layouts and key bindings are +;; supplied, including binding that emulate Eclipse and NetBeans. +;; The user can easily provide their own window layout and +;; settings. +;; +;; The default window layout looks like the following: +;; +;; +----------------------------------------------------------------------+ +;; | Toolbar | +;; +-----------------------------------+----------------------------------+ +;; | Debugger shell | Variables buffer | +;; +-----------------------------------+----------------------------------+ +;; | | | +;; | Source buffer | Output buffer | +;; | | | +;; +-----------------------------------+----------------------------------+ +;; | Stack buffer | Breakpoints buffer | +;; +-----------------------------------+----------------------------------+ +;; + +;; +;; Installation: +;; +;; To use this package, place the following line in an appropriate +;; init file (for example ~/.emacs): +;; +;; (require 'rdebug) +;; + +;; +;; History and Future: +;; +;; The design of this debugger user interface was inspired by +;; `gdb-ui', a similar user interface to GDB. +;; +;; Hopefully, rdebug, gdb-ui, and other emacs user interfaces could +;; join forces to create a common user-level look and feel, and a +;; battery of underlying support functions. +;; + +;; +;; This file contains only user-customizable variables and code to +;; load the other files when needed. +;; + +;;; Code: + +;; ------------------------------------------------------------------- +;; Consistency checks. +;; + +(if (< emacs-major-version 22) + (error + "This version of rdebug.el needs at least Emacs 22 or greater - you have version %d." + emacs-major-version)) + + +;; ------------------------------------------------------------------- +;; Support functions. +;; + +(defun rdebug-directory () + "The directory of this file, or nil." + (let ((file-name (or load-file-name + (symbol-file 'rdebug-directory)))) + (if file-name + (file-name-directory file-name) + nil))) + + +(defun rdebug-compare-filenames (f1 f2) + "Canonicalize and compare file names." + ;; Canonicalize by: + ;; 1) file-truename ensures that the file has got the correct case, + ;; and that "..":s in the path are eliminated. + ;; 2) file-name-as-directory ensures "/foo" and "/foo/" becomes equal. + + ;; Note: for some reason, when the `comp-elisp' external program is + ;; used, `nil' is part of `load-path'. + (if f1 + (setq f1 (file-name-as-directory (file-truename f1)))) + (if f2 + (setq f2 (file-name-as-directory (file-truename f2)))) + (equal f1 f2)) + + +;; Add the directory of `rdebug.el' to the load-path. This ensures +;; that all the user have do to use this package is to load this file. +(let ((dir (rdebug-directory))) + (if dir + (add-to-list 'load-path dir nil 'rdebug-compare-filenames))) + + +;; ------------------------------------------------------------------- +;; Autoloads. +;; + +(autoload 'rdebug "rdebug-core" + "Run the rdebug Ruby debugger and start the Emacs user interface. + +By default, the \"standard\" user window layout looks like the following: + ++----------------------------------------------------------------------+ +| Toolbar | ++-----------------------------------+----------------------------------+ +| Debugger shell | Variables buffer | ++-----------------------------------+----------------------------------+ +| | | +| Source buffer | Output buffer | +| | | ++-----------------------------------+----------------------------------+ +| Stack buffer | Breakpoints buffer | ++-----------------------------------+----------------------------------+ + +The variable `rdebug-many-windows-layout-function' can be +customized so that another layout is used. In addition to a +number of predefined layouts it's possible to define a function +to perform a custom layout. + +If `rdebug-many-windows' is nil, only a traditional debugger +shell and source window is opened. + +The directory containing the debugged script becomes the initial +working directory and source-file directory for your debugger. + +The custom variable `gud-rdebug-command-name' sets the command +and options used to invoke rdebug." t) + + +(autoload 'rdebug-turn-on-debugger-support "rdebug-source" + "Enable extra source buffer support for the `rdebug' Ruby debugger. + +This includes a 'Debugger' menu and special key bindings when the +debugger is active." + t) + + +(autoload 'rdebug-track-attach "rdebug-track" + "Do things to make the current process buffer work like a +rdebug command buffer." t) + +(autoload 'turn-on-rdebug-track-mode "rdebug-track" + "Turn on rdebugtrack mode. + +This function is designed to be added to hooks, for example: + (add-hook 'comint-mode-hook 'turn-on-rdebugtrack-mode)" + t) + + +(add-hook 'ruby-mode-hook 'rdebug-turn-on-debugger-support) + +;; This is needed, or at least the docstring part of it is needed to +;; get the customization menu to work in Emacs 23. +(defgroup rdebug nil + "The Ruby debugger" + :group 'processes + :group 'tools) + +;; ------------------------------------------------------------------- +;; User definable variables +;; + +(defcustom gud-rdebug-command-name + "rdebug --emacs 3" + "File name for executing the Ruby debugger and command options. +This should be an executable on your path, or an absolute file name." + :type 'string + :group 'gud) + +(defcustom rdebug-line-width 120 + "Length of line before truncation occurs. +This value limits output in secondary buffers." + :type 'integer + :group 'rdebug) + +(defcustom rdebug-many-windows t + "*If non-nil, use the full debugger user interface, see `rdebug'. + +However only set to the multi-window display if the rdebug +command invocation has an annotate options (\"--annotate 3\")." + :type 'boolean + :group 'rdebug) + +(defcustom rdebug-use-separate-io-buffer t + "*If non-nil, output goes to a dedicated windows. + +This only applies when `rdebug-many-windows' is non-nil." + :type 'boolean + :group 'rdebug) + +(defcustom rdebug-populate-common-keys-function + 'rdebug-populate-common-keys-standard + "The function to call to populate key bindings common to all rdebug windows. +This includes the secondary windows, the debugger shell, and all +Ruby source buffers when the debugger is active. + +This variable can be bound to the following: + +* nil -- Don't bind any keys. + +* `rdebug-populate-common-keys-standard' -- Bind according to a widely used + debugger convention: + +\\{rdebug-example-map-standard} + +* `rdebug-populate-common-keys-eclipse' -- Bind according to Eclipse. + +\\{rdebug-example-map-eclipse} + +* `rdebug-populate-common-keys-netbeans' -- Bind according to NetBeans. + +\\{rdebug-example-map-netbeans} + +* Any other value is expected to be a callable function that takes one + argument, the keymap, and populates it with suitable keys." + :type 'function + :group 'rdebug) + +(defcustom rdebug-restore-original-window-configuration :many + "*Control if the original window layout is restored when the debugger exits. +The value can be t, nil, or :many. + +A value of t means that the original layout is always restored, +nil means that it's never restored. + +:many means that the original layout is restored only when +`rdebug-many-windows' is used." + :type '(choice (const :tag "Always restore" t) + (const :tag "Never restore" nil) + (const :tag "Restore in many windows mode" :many)) + :group 'rdebug) + +(defcustom rdebug-use-separate-io-buffer t + "Non-nil means display output from the debugged program in a separate buffer." + :type 'boolean + :group 'gud) + + +(defcustom rdebug-window-layout-function + 'rdebug-window-layout-standard + "*A function that performs the window layout of `rdebug'. + +This is only used in `rdebug-many-windows' mode. This should be +bound to a function that performs the actual window layout. The +function should takes two arguments, the first is the source +buffer and the second the name of the script to debug. + +Rdebug provides the following predefined layout functions: + +* `rdebug-window-layout-standard' -- See `rdebug' + +* `rdebug-window-layout-no-shell' -- Standard + Display, no Shell + +* `rdebug-window-layout-conservative' -- Source + Shell + Output + +* `rdebug-window-layout-stack-of-windows' -- Extra windows to the right + +* `rdebug-window-layout-rocky' -- Rocky's own layout" + :type + '(choice + (function :tag "Standard" rdebug-window-layout-standard) + (function :tag "Conservative" rdebug-window-layout-conservative) + (function :tag "Stack of windows" rdebug-window-layout-stack-of-windows) + (function :tag "Rocky's own" rdebug-window-layout-rocky) + (function :tag "Rocky's II" rdebug-window-layout-rocky2) + (function :tag "Other" function)) + :group 'rdebug) + +(defcustom rdebug-source-location-ring-size 150 + "Size of rdebug position history ring." + :type 'integer + :group 'rdebug) + + +;; ------------------------------------------------------------------- +;; The end. +;; + +(provide 'rdebug) + +;;; rdebug.el ends here diff --git a/emacs/test/.svn/README.txt b/emacs/test/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/emacs/test/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/emacs/test/.svn/empty-file b/emacs/test/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/emacs/test/.svn/entries b/emacs/test/.svn/entries new file mode 100644 index 0000000..21a4c0c --- /dev/null +++ b/emacs/test/.svn/entries @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + diff --git a/emacs/test/.svn/format b/emacs/test/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/emacs/test/.svn/format @@ -0,0 +1 @@ +4 diff --git a/emacs/test/.svn/prop-base/elk-test.el.svn-base b/emacs/test/.svn/prop-base/elk-test.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/elk-test.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-annotate.el.svn-base b/emacs/test/.svn/prop-base/test-annotate.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-annotate.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-cmd.el.svn-base b/emacs/test/.svn/prop-base/test-cmd.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-cmd.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-core.el.svn-base b/emacs/test/.svn/prop-base/test-core.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-core.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-fns.el.svn-base b/emacs/test/.svn/prop-base/test-fns.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-fns.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-frames.el.svn-base b/emacs/test/.svn/prop-base/test-frames.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-frames.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-gud.el.svn-base b/emacs/test/.svn/prop-base/test-gud.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-gud.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-indent.el.svn-base b/emacs/test/.svn/prop-base/test-indent.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-indent.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-regexp.el.svn-base b/emacs/test/.svn/prop-base/test-regexp.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-regexp.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/prop-base/test-shortkey.el.svn-base b/emacs/test/.svn/prop-base/test-shortkey.el.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/prop-base/test-shortkey.el.svn-base @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/elk-test.el.svn-work b/emacs/test/.svn/props/elk-test.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/elk-test.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-annotate.el.svn-work b/emacs/test/.svn/props/test-annotate.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-annotate.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-cmd.el.svn-work b/emacs/test/.svn/props/test-cmd.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-cmd.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-core.el.svn-work b/emacs/test/.svn/props/test-core.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-core.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-fns.el.svn-work b/emacs/test/.svn/props/test-fns.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-fns.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-frames.el.svn-work b/emacs/test/.svn/props/test-frames.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-frames.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-gud.el.svn-work b/emacs/test/.svn/props/test-gud.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-gud.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-indent.el.svn-work b/emacs/test/.svn/props/test-indent.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-indent.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-regexp.el.svn-work b/emacs/test/.svn/props/test-regexp.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-regexp.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/props/test-shortkey.el.svn-work b/emacs/test/.svn/props/test-shortkey.el.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/emacs/test/.svn/props/test-shortkey.el.svn-work @@ -0,0 +1 @@ +END diff --git a/emacs/test/.svn/text-base/elk-test.el.svn-base b/emacs/test/.svn/text-base/elk-test.el.svn-base new file mode 100644 index 0000000..ddfc03c --- /dev/null +++ b/emacs/test/.svn/text-base/elk-test.el.svn-base @@ -0,0 +1,242 @@ +;;; elk-test.el --- Emacs Lisp testing suite + +;; Copyright (C) 2006 Nikolaj Schumacher + +;;; License + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License +;; as published by the Free Software Foundation; either version 2 +;; of the License, or (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;;; Usage + +;; Use `deftest' to define a test and `run-elk-test' to run it. +;; Create test bundles with `defsuite' or `build-suite'. +;; Verify your code with `assert-equal', `assert-eq', `assert-eql', +;; `assert-nonnil', `assert-t', `assert-nil' and `assert-error' +;; to verify your code. + +;;; Examples + +;; (deftest "test1" +;; (assert-equal t t) +;; (assert-eq t 'foo)) + +;; (defsuite "suite1" +;; (deftest "test1" (assert-equal t t))) + +;; (deftest "test2" +;; (assert-equal t t)) +;; (build-suite "combined-suite" "test1" "test2") + +;; (run-elk-test "combined-suite") +;; (run-elk-test) + +(require 'cl) + +(defvar elk-test-run-on-define nil + "If non-nil, run elk-test tests/suites immediately when defining them.") + +(defvar elk-test-map (make-hash-table :test 'equal) + "A map of elk-test test/suite names to their implementation.") + +(defvar elk-test-list nil + "A list of all defined elk-test tests/suites.") + +(defun elk-test-clear () + "Remove all tests from memory." + (setq elk-test-map (make-hash-table :test 'equal) + elk-test-list nil)) + +(defun run-elk-test (name &optional string-result) + "Run the test case defined as NAME. +The result is a list of errors strings, unless STRING-RESULT is set, in which +case a message describing the errors or success is displayed and returned." + (interactive + (list (completing-read "Test name: " elk-test-list nil t))) + (let ((name name)) + (let ((elk-test-errors nil) + (test-or-suite (gethash name elk-test-map))) + (if (not test-or-suite) + (error "Undefined test <%s>" name) + (if (equal (car test-or-suite) 'suite) + ;; is test suite + (let ((map (cadr test-or-suite))) + (dolist (test (caddr test-or-suite)) + (setq elk-test-errors + (append elk-test-errors + (run-elk-test-internal (gethash test map)))))) + ;; is simple test + (setq elk-test-errors (run-elk-test-internal test-or-suite))) + (if (or string-result (interactive-p)) + (message (if elk-test-errors + (mapconcat 'identity elk-test-errors "\n") + "Test run was successful.")) + elk-test-errors))))) + +(defun run-elk-tests-buffer (&optional buffer) + "Execute BUFFER as lisp code and run all tests therein." + (interactive) + (let* ((elk-test-list) + (elk-test-map (make-hash-table :test 'equal)) + (elk-test-run-on-define nil) + (inhibit-read-only t) + (buffer-name (buffer-name buffer)) + (success t) + (parse-res (condition-case err (eval-buffer buffer) (error err)))) + (if parse-res + (message "Parsing buffer <%s> failed:\n%s" + buffer-name parse-res) + (let ((out-buffer (get-buffer-create + (concat "*elk-test run " buffer-name "*"))) + failure) + (with-current-buffer out-buffer + (erase-buffer) + (dolist (test elk-test-list) + (message "running <%s>" test) + (let ((results (run-elk-test test))) + (when results + (setq failure t) + (insert "test <" test "> failed:\n") + (dolist (result results) + (insert "* " result "\n")))))) + (if failure + (display-buffer out-buffer) + (kill-buffer out-buffer) + (message "Test run was successful.")))))) + +(defun run-elk-test-internal (test) + (let ((elk-test-errors nil)) + (dolist (sexpr test) + (let ((problem (condition-case err (progn (eval sexpr) nil) (error err)))) + (when problem + (push (message "%s" problem) elk-test-errors)))) + elk-test-errors)) + +(defmacro elk-test-error (format-string &rest args) + "Create an error string as the result of a failed elk-test assertion. +The first argument is a format control string, and the rest are data to be +formatted under control of the string. See `format' for details. + +The result will be displayed, returned and if called inside of `run-elk-test' +added to the internal error list." + `(let ((string (message ,format-string ,@args))) + (when (boundp 'elk-test-errors) + (push string elk-test-errors)) + string)) + +(defmacro assert-equal (expected actual) + "Assert that ACTUAL equals EXPECTED, or signal a warning." + `(unless (equal ,expected ,actual) + (elk-test-error "assert-equal for <%s> failed: expected <%s>, was <%s>" + ',actual ,expected ,actual))) + +(defmacro assert-eq (expected actual) + "Assert that ACTUAL equals EXPECTED, or signal a warning." + `(unless (eq ,expected ,actual) + (elk-test-error "assert-eq for <%s> failed: expected <%s>, was <%s>" + ',actual ,expected ,actual))) + +(defmacro assert-eql (expected actual) + "Assert that ACTUAL equals EXPECTED, or signal a warning." + `(unless (eql ,expected ,actual) + (elk-test-error "assert-eql for <%s> failed: expected <%s>, was <%s>" + ',actual ,expected ,actual))) + +(defmacro assert-nonnil (value) + "Assert that VALUE is not nil, or signal a warning." + `(unless ,value + (elk-test-error "assert-nonnil for <%s> failed: was <%s>" + ',value ,value))) + +(defmacro assert-t (value) + "Assert that VALUE is t, or signal a warning." + `(unless (eq ,value t) + (elk-test-error "assert-t for <%s> failed: was <%s>" + ',value ,value))) + +(defmacro assert-nil (value) + "Assert that VALUE is nil, or signal a warning." + `(when ,value + (elk-test-error "assert-nil for <%s> failed: was <%s>" + ',value ,value))) + +(defmacro assert-error (error-message &rest body) + "Assert that BODY raises an `error', or signal a warning. +ERROR-MESSAGE is the expected error string, use nil to accept any error. Use +nil with caution, as errors like 'wrong-number-of-arguments' (likely caused by +typos) will also be caught!" + `(let ((elk-test-error + (condition-case elk-test-error + (progn ,@body) + (error (cons 'elk-test-error (cadr elk-test-error)))))) + (if (not (eq (car elk-test-error) 'elk-test-error)) + ;; no error + (elk-test-error "assert-error for <%s> failed: did not raise an error" + (append '(progn) ',body)) + (when (and ,error-message + (not (equal ,error-message (cdr elk-test-error)))) + (elk-test-error (concat "assert-error for <%s> failed: expected <%s>, " + "raised <%s>") + (append '(progn) ',body) + ,error-message (cdr elk-test-error)))))) + +(defmacro deftest (name &rest body) + "Define a test case. +Use `assert-equal', `assert-eq', `assert-eql', `assert-nonnil', `assert-t', +`assert-nil' and `assert-error' to verify the code." + `(progn (unless (gethash ,name elk-test-map) + (push ,name elk-test-list)) + (puthash ,name ',body elk-test-map) + ,(if elk-test-run-on-define + `(run-elk-test ',name ,t) + name))) + +(defmacro defsuite (name &rest body) + "Define a test suite using a collection of `deftest' forms. +The resulting suite can be called with `run-elk-test' and parameter NAME." + `(let ((suite + (let ((elk-test-map (make-hash-table :test 'equal)) + (elk-test-list nil)) + ,@body + (list 'suite elk-test-map (reverse elk-test-list))))) + (unless (gethash ,name elk-test-map) + (push ,name elk-test-list)) + (puthash ,name suite elk-test-map) + ,(if elk-test-run-on-define + `(run-elk-test ,name t) + name))) + +(defun build-suite (name &rest tests) + "Define a test suite using a collection of test names. +The resulting suite can be run by calling `run-elk-test' with parameter NAME." + (unless (gethash name elk-test-map) + (push name elk-test-list)) + (puthash name + (let ((map (make-hash-table :test 'equal)) + (list nil)) + (dolist (test-name tests) + (push test-name list) + (when (gethash test-name map) + (error "Test used twice")) + (let ((test (gethash test-name elk-test-map))) + (unless test + (error "Undefined test <%s>" test-name)) + (puthash test-name test map))) + (list 'suite map (reverse list))) + elk-test-map) + (if elk-test-run-on-define + (run-elk-test "sample suite" t) + name)) + +(provide 'elk-test) diff --git a/emacs/test/.svn/text-base/test-annotate.el.svn-base b/emacs/test/.svn/text-base/test-annotate.el.svn-base new file mode 100644 index 0000000..2042985 --- /dev/null +++ b/emacs/test/.svn/text-base/test-annotate.el.svn-base @@ -0,0 +1,103 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(load-file "../rdebug.el") +(load-file "../rdebug-annotate.el") + +(defvar last-annotation nil + "Value of the last annotation processed") + +;; Redefine functions to make them harmless for testing +(defun rdebug-process-annotation (name contents) + (setq last-annotation name)) + +(make-variable-buffer-local 'gud-rdebug-marker-acc) + +;; ------------------------------------------------------------------- +;; Test harness for testing the filter. +;; + +(require 'advice) + +(defvar rdebug-test-cmd-list '()) + +;; Override, partially because tooltip-show doesn't work in batch +;; mode, and partially because we collect the output here. +(defun tooltip-show (text) + (setq rdebug-test-cmd-list (cons text rdebug-test-cmd-list))) + +(defun assert-filter (output str &optional cmd-list) + (setq rdebug-test-cmd-list '()) + (setq gud-marker-acc "") + (let ((orig-queue rdebug-call-queue)) + (let ((real-output (gud-rdebug-marker-filter str))) + (assert-equal output real-output) + (assert-equal cmd-list (reverse rdebug-test-cmd-list))) + + ;; + ;; Feed the filter one character at a time -- the end result should + ;; be the same. + ;; + (setq rdebug-test-cmd-list '()) + (setq gud-marker-acc "") + (let ((real-output "") + (len (length str)) + (i 0) + (rdebug-call-queue orig-queue)) + (while (< i len) + (setq real-output + (concat real-output + (gud-rdebug-marker-filter + (substring str i (if (equal (+ 1 i) len) + nil + (+ 1 i)))))) + (setq i (+ 1 i))) + (assert-equal output real-output) + (assert-equal cmd-list (reverse rdebug-test-cmd-list))))) + + +(deftest "rdebug-filter" +;;; (assert-filter "X" "X") +;;; (assert-filter "XYZ" "XYZ") +;;; (assert-filter "" "\n") +;;; (assert-filter "Testing 1 2 3" "Testing 1 2 3") +;;; (assert-filter "Testing 1 2 3" "Testing 1 2 3") +;;; (assert-filter "ABC" "\ +;;; breakpoints +;;; No breakpoints +;;;  +;;; ABC") + + ;; Some systems (read: Mac) echoes the command. + (setq rdebug-call-queue '(("pp 100" :tooltip))) + (assert-filter "pp 100\n100\n(rdb:1) " "\ +prompt +pp 100\n100 +pre-prompt +\(rdb:1) \nprompt\n" + '("100\n")) + + ;; Some systems don't echo the command. + (setq rdebug-call-queue '(("pp 100" :tooltip))) + (assert-filter "100\n(rdb:1) " "\ +prompt +100 +pre-prompt +\(rdb:1) \nprompt\n" + '("100\n")) + ) + + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-filter") + +(run-elk-test "rdebug-suite" + "test regular expressions used in tracking lines") diff --git a/emacs/test/.svn/text-base/test-cmd.el.svn-base b/emacs/test/.svn/text-base/test-cmd.el.svn-base new file mode 100644 index 0000000..972ec1b --- /dev/null +++ b/emacs/test/.svn/text-base/test-cmd.el.svn-base @@ -0,0 +1,116 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +(setq load-path (cons ".." load-path)) +(require 'rdebug-core) +(require 'rdebug-gud) +(setq load-path (cdr load-path)) + +(defvar last-gud-call nil + "Value of the last gud-call") + +;; Redefine functions to make them harmless for testing +(defun gud-call (command) + (setq last-gud-call command)) + +(defun rdebug-call (command) + (setq last-gud-call command)) + +(deftest "rdebug-goto-frame-test" + (let ((buf (generate-new-buffer "testing"))) + (save-excursion + (switch-to-buffer buf) + (insert "#0 ERB.result(b#Binding) at line /usr/lib/ruby/1.8/erb.rb:736\n") + (insert "#1 Listings.build at line erbtest.rb:24\n") + (insert "#2 at line erbtest.rb:33\n") + (insert "#10 Listings.build at line erbtest.rb:23") + (goto-char (point-min)) + (setq last-gud-call nil) + (setq rdebug-goto-entry-acc "") + + ;; -------------------- + ;; The tests + + (rdebug-goto-frame-n-internal "5") + (assert-equal nil last-gud-call) + (rdebug-goto-frame-n-internal "1") + (assert-equal "frame 1" last-gud-call) + (rdebug-goto-frame-n-internal "0") + (assert-equal "frame 10" last-gud-call)) + (kill-buffer buf))) + + +;; ------------------------------------------------------------------- +;; Check breakpoint toggle commands +;; + +(deftest "rdebug-toggle-breakpoints" + (let ((buf (generate-new-buffer "*rdebug-breakpoint-test.rb*")) + ;; Needed by `rdebug-breakpoint-parse-and-update-cache'. + (gud-comint-buffer (current-buffer))) + (save-excursion + (switch-to-buffer buf) + (insert "Num Enb What\n") + (insert " 1 y at /test.rb:10\n") + (insert " 2 n at /test.rb:11\n") + (insert " 3 y at /test.rb:12\n") + (insert " 4 y at /test.rb:13\n") + (rdebug-breakpoint-parse-and-update-cache)) + (setq gud-target-name "test.rb") + + ;; ---------- + ;; Toggle break point + (assert-equal 4 (length (rdebug-all-breakpoints))) + + ;; ---------- + ;; Toggle break point + + ;; Add new. + (rdebug-toggle-source-breakpoint "/test.rb" 20) + (assert-equal "break /test.rb:20" last-gud-call) + ;; Delete enabled. + (rdebug-toggle-source-breakpoint "/test.rb" 10) + (assert-equal "delete 1" last-gud-call) + ;; Delete disabled. + (rdebug-toggle-source-breakpoint "/test.rb" 11) + (assert-equal "delete 2" last-gud-call) + + ;; ---------- + ;; Toggle enable/disable. + + ;; Add new. + (rdebug-toggle-source-breakpoint-enabled "/test.rb" 30) + (assert-equal "break /test.rb:30" last-gud-call) + + ;; Toggle enabled. + (rdebug-toggle-source-breakpoint-enabled "/test.rb" 10) + (assert-equal "disable 1" last-gud-call) + ;; Toggle disabled. + (rdebug-toggle-source-breakpoint-enabled "/test.rb" 11) + (assert-equal "enable 2" last-gud-call))) + + +;; ------------------------------------------------------------------- +;; Check rdebug-next with prefix toggling commands +;; +(deftest "rdebug-stepping-test" + (setq rdebug-stepping-prefix "") + (assert-equal "next 1" (rdebug-next)) + (setq rdebug-stepping-prefix "-") + (assert-equal "next- 2" (rdebug-next 2)) + (setq rdebug-stepping-prefix "+") + (assert-equal "step+ 1" (rdebug-step)) + ) + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-cmd-suite" + "rdebug-goto-frame-test" + "rdebug-stepping-test" + "rdebug-toggle-breakpoints") +(run-elk-test "rdebug-cmd-suite" + "test some rdebug-core code") diff --git a/emacs/test/.svn/text-base/test-core.el.svn-base b/emacs/test/.svn/text-base/test-core.el.svn-base new file mode 100644 index 0000000..206b60a --- /dev/null +++ b/emacs/test/.svn/text-base/test-core.el.svn-base @@ -0,0 +1,104 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(load-file "../rdebug.el") +(load-file "../rdebug-core.el") + +;; Redefine functions to make them harmless for testing +(defun rdebug-process-annotation (name contents) + (message name) + ) + +(make-variable-buffer-local 'gud-rdebug-marker-acc) + +(deftest "rdebug-get-script-name-test" + (assert-equal '("foo" nil) (rdebug-get-script-name '("rdebug" "foo"))) + (assert-equal '("foo" nil) (rdebug-get-script-name '("rdebug" "-m" "foo"))) + (assert-equal '("foo" t) (rdebug-get-script-name + '("rdebug" "--emacs" "3" "foo"))) + (assert-equal '("foo" t) (rdebug-get-script-name + '("myrdebug" "--annotate=1" "foo"))) + (assert-equal '("foo" t) (rdebug-get-script-name + '("ruby" "rdebug" "--annotate" "1" "foo"))) + (assert-equal '("foo" nil) (rdebug-get-script-name + '("/usr/bin/ruby19" "rdebug" "--emacs-basic" "foo"))) + (assert-equal '("foo" nil) (rdebug-get-script-name + '("rdbg.rb" "foo"))) + (assert-equal '("rdbg.rb" nil) (rdebug-get-script-name + '("rdebug" "rdbg.rb" "foo"))) + (assert-equal '("foo" t) (rdebug-get-script-name '("rdebug" "-A" "1" "foo"))) + (assert-equal '("foo" nil) + (rdebug-get-script-name + '("rdebug" "--include" "me" "-n" "foo"))) + (assert-equal '("foo" nil) (rdebug-get-script-name + '("rdebug" "--server" "-d" "--host" + "localhost" "foo" "-1"))) + ) + +(deftest "rdebug-goto-entry-test" + (let ((buf (generate-new-buffer "testing"))) + (save-excursion + (switch-to-buffer buf) + (insert "#0 at line /tmp/gcd.rb:4\n") + (goto-char (point-min)) + (assert-equal t (rdebug-goto-entry-try "0")) + (assert-equal nil (rdebug-goto-entry-try "1")) + (insert " 1 y at gcd.rb:10\n") + (goto-char (point-min)) + ;; Don't know why this doesn't work. + ;;(assert-equal t (rdebug-goto-entry-try "1")) + (insert "5: 1 + 2 = 3\n") + (goto-char (point-min)) + (assert-equal t (rdebug-goto-entry-try "5")) + (goto-char (point-min)) + (assert-equal nil (rdebug-goto-entry-try "3"))) + (kill-buffer buf))) + +(defun rdebug-test-call-entry-n (str) + "Call `rdebug-goto-entry-n', return the line we landed on." + (rdebug-goto-entry-n-internal str) + (beginning-of-line) + (count-lines (point-min) (point))) + +;; The original implementation could not go to "10" if there was no "1" entry. +(deftest "rdebug-goto-entry-test-2" + (let ((buf (generate-new-buffer "testing"))) + (save-excursion + (switch-to-buffer buf) + (insert "#0 at line /tmp/gcd.rb:4\n") + (insert "#2 at line /tmp/gcd.rb:44\n") + (insert "#13 at line /tmp/gcd.rb:444\n") + (goto-char (point-min)) + (setq rdebug-goto-entry-acc "") + ;; Goto "0" + (assert-equal 0 (rdebug-test-call-entry-n "0")) + ;; Goto "2" + (assert-equal 1 (rdebug-test-call-entry-n "2")) + ;; There is no "1" or "21" or "021", so stay. + (assert-equal 1 (rdebug-test-call-entry-n "1")) + ;; Goto "13" + (assert-equal 2 (rdebug-test-call-entry-n "3")) + ;; There is no "5", "35", or "135", so stay. + (assert-equal 2 (rdebug-test-call-entry-n "5")) + ;; Goto "0" + (assert-equal 0 (rdebug-test-call-entry-n "0")) + ;; Goto "2" + (assert-equal 1 (rdebug-test-call-entry-n "2"))) + (kill-buffer buf))) + + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-get-script-name-test" + "rdebug-goto-entry-test" + "rdebug-goto-entry-test-2") +(run-elk-test "rdebug-suite" + "test things in rdebug-core.el") + diff --git a/emacs/test/.svn/text-base/test-fns.el.svn-base b/emacs/test/.svn/text-base/test-fns.el.svn-base new file mode 100644 index 0000000..89341cf --- /dev/null +++ b/emacs/test/.svn/text-base/test-fns.el.svn-base @@ -0,0 +1,65 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +(setq load-path (cons ".." load-path)) +(require 'rdebug-fns) +(require 'rdebug-locring) +(setq load-path (cdr load-path)) + +;; ------------------------------------------------------------------- + +(deftest "test-add-to-ring" + (let ((location-ring (make-ring 5))) + (assert-equal t (ring-empty-p location-ring)) + (rdebug-locring-add 'first location-ring) + (assert-equal 'first (ring-ref location-ring 0)) + (assert-equal 1 (ring-length location-ring)) + ;; Trying to add the same entry should not again. + (rdebug-locring-add 'first location-ring) + (assert-equal 1 (ring-length location-ring)) + + ;; Second should go in as last item. + (rdebug-locring-add 'second location-ring) + (assert-equal 'second (ring-ref location-ring 1)) + ;; First item is still 0. + (assert-equal 'first (ring-ref location-ring 0)))) + +(deftest "test-chomp" + (assert-equal "" (chomp "")) + (assert-equal "hi" (chomp "hi")) + (assert-equal "hi" (chomp "hi\n")) + (assert-equal "hi\n" (chomp "hi\n\n")) + (assert-equal "hi" (chomp "hi\n\n" t))) + +(deftest "test-set-frame-arrow" + (let ((rdebug-frames-current-frame-number 0)) + (rdebug-set-frame-arrow (current-buffer)) + (assert-equal '((overlay-arrow . right-triangle)) + fringe-indicator-alist) + (setq rdebug-frames-current-frame-number 1) + (rdebug-set-frame-arrow (current-buffer)) + (assert-equal '((overlay-arrow . hollow-right-triangle)) + fringe-indicator-alist))) + +(require 'shell) +(deftest "test-dead-process-p" + (assert-equal t (rdebug-dead-process-p)) + (let ((gud-comint-buffer nil)) + (assert-equal t (rdebug-dead-process-p)) + (setq gud-comint-buffer (shell)) + (assert-equal nil (rdebug-dead-process-p)))) + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-gud-suite" + "test-add-to-ring" + "test-chomp" + "test-dead-process-p" + "test-set-frame-arrow") + +(run-elk-test "rdebug-gud-suite" + "test some rdebug-error code") diff --git a/emacs/test/.svn/text-base/test-frames.el.svn-base b/emacs/test/.svn/text-base/test-frames.el.svn-base new file mode 100644 index 0000000..c491f75 --- /dev/null +++ b/emacs/test/.svn/text-base/test-frames.el.svn-base @@ -0,0 +1,62 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(load-file "../rdebug.el") +(load-file "../rdebug-regexp.el") +(load-file "../rdebug-frames.el") + +(make-variable-buffer-local 'gud-rdebug-marker-acc) + +(deftest "rdebug-stack-buffer-field-test" + (let ((buf (generate-new-buffer "testing"))) + (save-excursion + (switch-to-buffer buf) + (insert + "--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line /tmp/gcd.rb:4\n") + (insert + " at line /foo/bar/custom_require.rb:27\n") + + (goto-char (point-min)) + (let* ((b (line-beginning-position)) (e (line-end-position)) + (s (buffer-substring b e)) + (file nil) (line nil)) + (assert-nonnil (string-match rdebug-stack-frame-regexp s)) + (assert-equal "/tmp/gcd.rb" (rdebug-stack-buffer-field + s b + rdebug-stack-frame-file-group + font-lock-comment-face)) + (assert-equal "4" (rdebug-stack-buffer-field + s b + rdebug-stack-frame-line-group + font-lock-constant-face)) + (forward-line) + (setq b (line-beginning-position)) + (setq e (line-end-position)) + (setq s (buffer-substring b e)) + (assert-nonnil (string-match rdebug-stack-frame-2nd-regexp s)) + (assert-equal "/foo/bar/custom_require.rb" + (rdebug-stack-buffer-field + s b + rdebug-stack-frame-2nd-file-group + font-lock-comment-face)) + (assert-equal "27" (rdebug-stack-buffer-field + s b + rdebug-stack-frame-2nd-line-group + font-lock-constant-face)) + )) + (kill-buffer buf))) + + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-stack-buffer-field-test") +(run-elk-test "rdebug-suite" + "test things in rdebug-frames.el") + diff --git a/emacs/test/.svn/text-base/test-gud.el.svn-base b/emacs/test/.svn/text-base/test-gud.el.svn-base new file mode 100644 index 0000000..ddf3c39 --- /dev/null +++ b/emacs/test/.svn/text-base/test-gud.el.svn-base @@ -0,0 +1,35 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +(setq load-path (cons ".." load-path)) +(require 'rdebug-gud) +(setq load-path (cdr load-path)) + +(defun y-or-n-p (prompt) + "Replacement of y-or-n-p() for rdebug testing" + (assert-nil "y-or-n-p should not have been called")) + +(defun error (msg) + "Replacement error() for rdebug testing" + (assert-nil "error should not have been called")) + +;; ------------------------------------------------------------------- + +(deftest "test-rdebug-find-file" + ;; Set to cause a warning in find-file-no-select and + ;; check that it is ignored. + (let ((large-file-warning-threshold 1)) + (gud-rdebug-find-file "elk-test.el"))) + + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-gud-suite" + "test-rdebug-find-file") + +(run-elk-test "rdebug-gud-suite" + "test some rdebug-gud code") diff --git a/emacs/test/.svn/text-base/test-indent.el.svn-base b/emacs/test/.svn/text-base/test-indent.el.svn-base new file mode 100644 index 0000000..ad4ec91 --- /dev/null +++ b/emacs/test/.svn/text-base/test-indent.el.svn-base @@ -0,0 +1,58 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; ------------------------------------------------------------------- +;; Check source code indentation +;; + +(put 'rdebug-debug-enter 'lisp-indent-hook 1) + +(defun rdebug-test-reindent-one-file (file) + (let ((buf (generate-new-buffer "testing")) + (res nil)) + (save-excursion + (switch-to-buffer buf) + (insert-file file) + (emacs-lisp-mode) + (set-buffer-modified-p nil) + (undo-boundary) + (indent-region (point-min) (point-max)) + (if (buffer-modified-p) + (setq res "Reindentation failed"))) + (kill-buffer buf) + res)) + +(deftest "rdebug-indent-files" + (mapcar (lambda (lisp-file) + (message lisp-file) + (assert-nil (rdebug-test-reindent-one-file lisp-file))) + '("../rdebug.el" + "../rdebug-breaks.el" + "../rdebug-cmd.el" + "../rdebug-core.el" + "../rdebug-dbg.el" + "../rdebug-error.el" + "../rdebug-frames.el" + "../rdebug-fns.el" + "../rdebug-gud.el" + "../rdebug-help.el" + "../rdebug-info.el" + "../rdebug-layouts.el" + "../rdebug-output.el" + "../rdebug-regexp.el" + "../rdebug-secondary.el" + "../rdebug-source.el" + "../rdebug-track.el" + "../rdebug-varbuf.el" + "../rdebug-vars.el" + "../rdebug-watch.el" + "./test-cmd.el" + "./test-core.el" + "./test-indent.el" + "./test-regexp.el" + ))) + +(run-elk-test "rdebug-indent-files" + "test indentation of Lisp files") diff --git a/emacs/test/.svn/text-base/test-regexp.el.svn-base b/emacs/test/.svn/text-base/test-regexp.el.svn-base new file mode 100644 index 0000000..790971e --- /dev/null +++ b/emacs/test/.svn/text-base/test-regexp.el.svn-base @@ -0,0 +1,144 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(load-file "../rdebug.el") +(load-file "../rdebug-core.el") + +(make-variable-buffer-local 'gud-rdebug-marker-acc) + +(defun regexp-breakpoint-test (location-str pos-str enabled-str file-str line-str) + "Test to see that location-str parses rdebug-breakpoint-regexp properly" + (assert-equal 0 (string-match rdebug-breakpoint-regexp location-str)) + (assert-equal pos-str + (substring location-str (match-beginning 1) (match-end 1))) + (assert-equal enabled-str + (substring location-str (match-beginning 2) (match-end 2))) + (assert-equal file-str + (substring location-str (match-beginning 3) (match-end 3))) + (assert-equal line-str + (substring location-str (match-beginning 4) (match-end 4))) + ) +(deftest "rdebug-regexp-breakpoint-test" + + (regexp-breakpoint-test + " 1 y at gcd.rb:6" + "1" "y" "gcd.rb" "6" + ) + (regexp-breakpoint-test + " 1 y at gcd.rb:6 if 1 == a" + "1" "y" "gcd.rb" "6" + ) + ) + +(defun regexp-file-test (location-str file-str) + "Test to see that location-str matches gud-rdebug-marker-regexp" + (assert-equal 0 (string-match gud-rdebug-marker-regexp location-str)) + (assert-equal file-str + (substring location-str (match-beginning 1) (match-end 1))) + ) +(deftest "rdebug-regexp-file-test" + + (regexp-file-test + "\032\032./hanoi.rb:3\n" + "./hanoi.rb" + ) + (regexp-file-test + "\032\032source ./hanoi.rb:3\n" + "./hanoi.rb" + ) + (regexp-file-test + "\032\032C:/tmp/gcd.rb:29\n" + "C:/tmp/gcd.rb" + ) + (regexp-file-test + "\032\032source \\sources\\capfilterscanner\\capanalyzer.rb:3: \n" + "\\sources\\capfilterscanner\\capanalyzer.rb" + ) + ) + +(deftest "rdebug-regexp-marker-filter-test" + (assert-equal "Testing 1 2 3" (gud-rdebug-marker-filter "Testing 1 2 3")) + (assert-equal "ABC" (gud-rdebug-marker-filter + "\ +breakpoints +No breakpoints + +ABC"))) + +(defun regexp-stack-test (location-str pos-str file-str line-str) + "Test to see that location-str parses rdebug-stack-frame-regexp properly" + (assert-equal 0 (string-match rdebug-stack-frame-regexp location-str)) + (assert-equal pos-str + (substring location-str (match-beginning 2) (match-end 2))) + (assert-equal file-str + (substring location-str (match-beginning 4) (match-end 4))) + (assert-equal line-str + (substring location-str (match-beginning 5) (match-end 5))) + ) +(deftest "rdebug-regexp-stack-test" + + (regexp-stack-test + "--> #0 at line /home/rocky/ruby/gcd.rb:18" + "0" "/home/rocky/ruby/gcd.rb" "18" + ) + ) + +(defun regexp-traceback-test (location-str file-str line-str) + "Test to see that location-str matches position-regexp-file-test with the correct +file and line submatches." + (assert-equal 0 (string-match rdebug-traceback-line-re location-str)) + (assert-equal file-str (match-string 1 location-str)) + (assert-equal line-str (match-string 2 location-str)) + ) + +(deftest "rdebug-regexp-traceback-test" + + (regexp-traceback-test + " from /home/rocky/ruby/gcd.rb:15:in `gcd'" + "/home/rocky/ruby/gcd.rb" "15" + ) + (regexp-traceback-test + " from /home/rocky/ruby/gcd.rb:19" + "/home/rocky/ruby/gcd.rb" "19" + ) + ) + +(defun regexp-unittest-traceback-test (location-str file-str line-str) + "Test to see that location-str matches position-regexp-file-test with the correct +file and line submatches." + (assert-equal 0 (string-match rdebug-dollarbang-traceback-line-re + location-str)) + (assert-equal file-str (match-string 1 location-str)) + (assert-equal line-str (match-string 2 location-str)) + ) + +(deftest "rdebug-regexp-unittest-traceback-test" + + (regexp-unittest-traceback-test + " [test-frame.rb:26:in `test_basic'" + "test-frame.rb" "26" + ) + (regexp-unittest-traceback-test + " test-frame.rb:22:in `test_basic']:" + "test-frame.rb" "22" + ) + ) + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-regexp-breakpoint-test" + "rdebug-regexp-file-test" + "rdebug-regexp-marker-filter-test" + "rdebug-regexp-stack-test" + "rdebug-regexp-traceback-test" + "rdebug-regexp-unittest-traceback-test") + +(run-elk-test "rdebug-suite" + "test regular expressions used in tracking lines") diff --git a/emacs/test/.svn/text-base/test-shortkey.el.svn-base b/emacs/test/.svn/text-base/test-shortkey.el.svn-base new file mode 100644 index 0000000..3318c40 --- /dev/null +++ b/emacs/test/.svn/text-base/test-shortkey.el.svn-base @@ -0,0 +1,61 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(setq load-path (cons ".." load-path)) +(load-file "../rdebug-shortkey.el") + +(deftest "rdebug-shortkey-mode-test" + (let ((buf (generate-new-buffer "shortkey readwrite"))) + (with-current-buffer buf + (setq buffer-read-only nil) + ;; turning on short-key-mode make buffer read-only + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + ;; turning off short-key-mode should make buffer read-write again + (rdebug-internal-short-key-mode -1) + (assert-equal nil buffer-read-only) + + ;; -------------------- + ;; Check multiple "on": and "off:s". + + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + (rdebug-internal-short-key-mode -1) + (assert-equal nil buffer-read-only)) + + (kill-buffer buf)) + + (let ((buf (generate-new-buffer "shortkey readonly"))) + (with-current-buffer buf + (setq buffer-read-only t) + + ;; turning on short-key-mode keep buffer read-only + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + ;; The buffer was originally in read-only mode, it should remain + ;; there. + (rdebug-internal-short-key-mode -1) + (assert-equal t buffer-read-only)) + (kill-buffer buf))) + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-shortkey-mode-test") +(run-elk-test "rdebug-suite" + "test things in rdebug-shortkey.el") diff --git a/emacs/test/elk-test.el b/emacs/test/elk-test.el new file mode 100644 index 0000000..ddfc03c --- /dev/null +++ b/emacs/test/elk-test.el @@ -0,0 +1,242 @@ +;;; elk-test.el --- Emacs Lisp testing suite + +;; Copyright (C) 2006 Nikolaj Schumacher + +;;; License + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License +;; as published by the Free Software Foundation; either version 2 +;; of the License, or (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;;; Usage + +;; Use `deftest' to define a test and `run-elk-test' to run it. +;; Create test bundles with `defsuite' or `build-suite'. +;; Verify your code with `assert-equal', `assert-eq', `assert-eql', +;; `assert-nonnil', `assert-t', `assert-nil' and `assert-error' +;; to verify your code. + +;;; Examples + +;; (deftest "test1" +;; (assert-equal t t) +;; (assert-eq t 'foo)) + +;; (defsuite "suite1" +;; (deftest "test1" (assert-equal t t))) + +;; (deftest "test2" +;; (assert-equal t t)) +;; (build-suite "combined-suite" "test1" "test2") + +;; (run-elk-test "combined-suite") +;; (run-elk-test) + +(require 'cl) + +(defvar elk-test-run-on-define nil + "If non-nil, run elk-test tests/suites immediately when defining them.") + +(defvar elk-test-map (make-hash-table :test 'equal) + "A map of elk-test test/suite names to their implementation.") + +(defvar elk-test-list nil + "A list of all defined elk-test tests/suites.") + +(defun elk-test-clear () + "Remove all tests from memory." + (setq elk-test-map (make-hash-table :test 'equal) + elk-test-list nil)) + +(defun run-elk-test (name &optional string-result) + "Run the test case defined as NAME. +The result is a list of errors strings, unless STRING-RESULT is set, in which +case a message describing the errors or success is displayed and returned." + (interactive + (list (completing-read "Test name: " elk-test-list nil t))) + (let ((name name)) + (let ((elk-test-errors nil) + (test-or-suite (gethash name elk-test-map))) + (if (not test-or-suite) + (error "Undefined test <%s>" name) + (if (equal (car test-or-suite) 'suite) + ;; is test suite + (let ((map (cadr test-or-suite))) + (dolist (test (caddr test-or-suite)) + (setq elk-test-errors + (append elk-test-errors + (run-elk-test-internal (gethash test map)))))) + ;; is simple test + (setq elk-test-errors (run-elk-test-internal test-or-suite))) + (if (or string-result (interactive-p)) + (message (if elk-test-errors + (mapconcat 'identity elk-test-errors "\n") + "Test run was successful.")) + elk-test-errors))))) + +(defun run-elk-tests-buffer (&optional buffer) + "Execute BUFFER as lisp code and run all tests therein." + (interactive) + (let* ((elk-test-list) + (elk-test-map (make-hash-table :test 'equal)) + (elk-test-run-on-define nil) + (inhibit-read-only t) + (buffer-name (buffer-name buffer)) + (success t) + (parse-res (condition-case err (eval-buffer buffer) (error err)))) + (if parse-res + (message "Parsing buffer <%s> failed:\n%s" + buffer-name parse-res) + (let ((out-buffer (get-buffer-create + (concat "*elk-test run " buffer-name "*"))) + failure) + (with-current-buffer out-buffer + (erase-buffer) + (dolist (test elk-test-list) + (message "running <%s>" test) + (let ((results (run-elk-test test))) + (when results + (setq failure t) + (insert "test <" test "> failed:\n") + (dolist (result results) + (insert "* " result "\n")))))) + (if failure + (display-buffer out-buffer) + (kill-buffer out-buffer) + (message "Test run was successful.")))))) + +(defun run-elk-test-internal (test) + (let ((elk-test-errors nil)) + (dolist (sexpr test) + (let ((problem (condition-case err (progn (eval sexpr) nil) (error err)))) + (when problem + (push (message "%s" problem) elk-test-errors)))) + elk-test-errors)) + +(defmacro elk-test-error (format-string &rest args) + "Create an error string as the result of a failed elk-test assertion. +The first argument is a format control string, and the rest are data to be +formatted under control of the string. See `format' for details. + +The result will be displayed, returned and if called inside of `run-elk-test' +added to the internal error list." + `(let ((string (message ,format-string ,@args))) + (when (boundp 'elk-test-errors) + (push string elk-test-errors)) + string)) + +(defmacro assert-equal (expected actual) + "Assert that ACTUAL equals EXPECTED, or signal a warning." + `(unless (equal ,expected ,actual) + (elk-test-error "assert-equal for <%s> failed: expected <%s>, was <%s>" + ',actual ,expected ,actual))) + +(defmacro assert-eq (expected actual) + "Assert that ACTUAL equals EXPECTED, or signal a warning." + `(unless (eq ,expected ,actual) + (elk-test-error "assert-eq for <%s> failed: expected <%s>, was <%s>" + ',actual ,expected ,actual))) + +(defmacro assert-eql (expected actual) + "Assert that ACTUAL equals EXPECTED, or signal a warning." + `(unless (eql ,expected ,actual) + (elk-test-error "assert-eql for <%s> failed: expected <%s>, was <%s>" + ',actual ,expected ,actual))) + +(defmacro assert-nonnil (value) + "Assert that VALUE is not nil, or signal a warning." + `(unless ,value + (elk-test-error "assert-nonnil for <%s> failed: was <%s>" + ',value ,value))) + +(defmacro assert-t (value) + "Assert that VALUE is t, or signal a warning." + `(unless (eq ,value t) + (elk-test-error "assert-t for <%s> failed: was <%s>" + ',value ,value))) + +(defmacro assert-nil (value) + "Assert that VALUE is nil, or signal a warning." + `(when ,value + (elk-test-error "assert-nil for <%s> failed: was <%s>" + ',value ,value))) + +(defmacro assert-error (error-message &rest body) + "Assert that BODY raises an `error', or signal a warning. +ERROR-MESSAGE is the expected error string, use nil to accept any error. Use +nil with caution, as errors like 'wrong-number-of-arguments' (likely caused by +typos) will also be caught!" + `(let ((elk-test-error + (condition-case elk-test-error + (progn ,@body) + (error (cons 'elk-test-error (cadr elk-test-error)))))) + (if (not (eq (car elk-test-error) 'elk-test-error)) + ;; no error + (elk-test-error "assert-error for <%s> failed: did not raise an error" + (append '(progn) ',body)) + (when (and ,error-message + (not (equal ,error-message (cdr elk-test-error)))) + (elk-test-error (concat "assert-error for <%s> failed: expected <%s>, " + "raised <%s>") + (append '(progn) ',body) + ,error-message (cdr elk-test-error)))))) + +(defmacro deftest (name &rest body) + "Define a test case. +Use `assert-equal', `assert-eq', `assert-eql', `assert-nonnil', `assert-t', +`assert-nil' and `assert-error' to verify the code." + `(progn (unless (gethash ,name elk-test-map) + (push ,name elk-test-list)) + (puthash ,name ',body elk-test-map) + ,(if elk-test-run-on-define + `(run-elk-test ',name ,t) + name))) + +(defmacro defsuite (name &rest body) + "Define a test suite using a collection of `deftest' forms. +The resulting suite can be called with `run-elk-test' and parameter NAME." + `(let ((suite + (let ((elk-test-map (make-hash-table :test 'equal)) + (elk-test-list nil)) + ,@body + (list 'suite elk-test-map (reverse elk-test-list))))) + (unless (gethash ,name elk-test-map) + (push ,name elk-test-list)) + (puthash ,name suite elk-test-map) + ,(if elk-test-run-on-define + `(run-elk-test ,name t) + name))) + +(defun build-suite (name &rest tests) + "Define a test suite using a collection of test names. +The resulting suite can be run by calling `run-elk-test' with parameter NAME." + (unless (gethash name elk-test-map) + (push name elk-test-list)) + (puthash name + (let ((map (make-hash-table :test 'equal)) + (list nil)) + (dolist (test-name tests) + (push test-name list) + (when (gethash test-name map) + (error "Test used twice")) + (let ((test (gethash test-name elk-test-map))) + (unless test + (error "Undefined test <%s>" test-name)) + (puthash test-name test map))) + (list 'suite map (reverse list))) + elk-test-map) + (if elk-test-run-on-define + (run-elk-test "sample suite" t) + name)) + +(provide 'elk-test) diff --git a/emacs/test/test-annotate.el b/emacs/test/test-annotate.el new file mode 100644 index 0000000..2042985 --- /dev/null +++ b/emacs/test/test-annotate.el @@ -0,0 +1,103 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(load-file "../rdebug.el") +(load-file "../rdebug-annotate.el") + +(defvar last-annotation nil + "Value of the last annotation processed") + +;; Redefine functions to make them harmless for testing +(defun rdebug-process-annotation (name contents) + (setq last-annotation name)) + +(make-variable-buffer-local 'gud-rdebug-marker-acc) + +;; ------------------------------------------------------------------- +;; Test harness for testing the filter. +;; + +(require 'advice) + +(defvar rdebug-test-cmd-list '()) + +;; Override, partially because tooltip-show doesn't work in batch +;; mode, and partially because we collect the output here. +(defun tooltip-show (text) + (setq rdebug-test-cmd-list (cons text rdebug-test-cmd-list))) + +(defun assert-filter (output str &optional cmd-list) + (setq rdebug-test-cmd-list '()) + (setq gud-marker-acc "") + (let ((orig-queue rdebug-call-queue)) + (let ((real-output (gud-rdebug-marker-filter str))) + (assert-equal output real-output) + (assert-equal cmd-list (reverse rdebug-test-cmd-list))) + + ;; + ;; Feed the filter one character at a time -- the end result should + ;; be the same. + ;; + (setq rdebug-test-cmd-list '()) + (setq gud-marker-acc "") + (let ((real-output "") + (len (length str)) + (i 0) + (rdebug-call-queue orig-queue)) + (while (< i len) + (setq real-output + (concat real-output + (gud-rdebug-marker-filter + (substring str i (if (equal (+ 1 i) len) + nil + (+ 1 i)))))) + (setq i (+ 1 i))) + (assert-equal output real-output) + (assert-equal cmd-list (reverse rdebug-test-cmd-list))))) + + +(deftest "rdebug-filter" +;;; (assert-filter "X" "X") +;;; (assert-filter "XYZ" "XYZ") +;;; (assert-filter "" "\n") +;;; (assert-filter "Testing 1 2 3" "Testing 1 2 3") +;;; (assert-filter "Testing 1 2 3" "Testing 1 2 3") +;;; (assert-filter "ABC" "\ +;;; breakpoints +;;; No breakpoints +;;;  +;;; ABC") + + ;; Some systems (read: Mac) echoes the command. + (setq rdebug-call-queue '(("pp 100" :tooltip))) + (assert-filter "pp 100\n100\n(rdb:1) " "\ +prompt +pp 100\n100 +pre-prompt +\(rdb:1) \nprompt\n" + '("100\n")) + + ;; Some systems don't echo the command. + (setq rdebug-call-queue '(("pp 100" :tooltip))) + (assert-filter "100\n(rdb:1) " "\ +prompt +100 +pre-prompt +\(rdb:1) \nprompt\n" + '("100\n")) + ) + + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-filter") + +(run-elk-test "rdebug-suite" + "test regular expressions used in tracking lines") diff --git a/emacs/test/test-cmd.el b/emacs/test/test-cmd.el new file mode 100644 index 0000000..972ec1b --- /dev/null +++ b/emacs/test/test-cmd.el @@ -0,0 +1,116 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +(setq load-path (cons ".." load-path)) +(require 'rdebug-core) +(require 'rdebug-gud) +(setq load-path (cdr load-path)) + +(defvar last-gud-call nil + "Value of the last gud-call") + +;; Redefine functions to make them harmless for testing +(defun gud-call (command) + (setq last-gud-call command)) + +(defun rdebug-call (command) + (setq last-gud-call command)) + +(deftest "rdebug-goto-frame-test" + (let ((buf (generate-new-buffer "testing"))) + (save-excursion + (switch-to-buffer buf) + (insert "#0 ERB.result(b#Binding) at line /usr/lib/ruby/1.8/erb.rb:736\n") + (insert "#1 Listings.build at line erbtest.rb:24\n") + (insert "#2 at line erbtest.rb:33\n") + (insert "#10 Listings.build at line erbtest.rb:23") + (goto-char (point-min)) + (setq last-gud-call nil) + (setq rdebug-goto-entry-acc "") + + ;; -------------------- + ;; The tests + + (rdebug-goto-frame-n-internal "5") + (assert-equal nil last-gud-call) + (rdebug-goto-frame-n-internal "1") + (assert-equal "frame 1" last-gud-call) + (rdebug-goto-frame-n-internal "0") + (assert-equal "frame 10" last-gud-call)) + (kill-buffer buf))) + + +;; ------------------------------------------------------------------- +;; Check breakpoint toggle commands +;; + +(deftest "rdebug-toggle-breakpoints" + (let ((buf (generate-new-buffer "*rdebug-breakpoint-test.rb*")) + ;; Needed by `rdebug-breakpoint-parse-and-update-cache'. + (gud-comint-buffer (current-buffer))) + (save-excursion + (switch-to-buffer buf) + (insert "Num Enb What\n") + (insert " 1 y at /test.rb:10\n") + (insert " 2 n at /test.rb:11\n") + (insert " 3 y at /test.rb:12\n") + (insert " 4 y at /test.rb:13\n") + (rdebug-breakpoint-parse-and-update-cache)) + (setq gud-target-name "test.rb") + + ;; ---------- + ;; Toggle break point + (assert-equal 4 (length (rdebug-all-breakpoints))) + + ;; ---------- + ;; Toggle break point + + ;; Add new. + (rdebug-toggle-source-breakpoint "/test.rb" 20) + (assert-equal "break /test.rb:20" last-gud-call) + ;; Delete enabled. + (rdebug-toggle-source-breakpoint "/test.rb" 10) + (assert-equal "delete 1" last-gud-call) + ;; Delete disabled. + (rdebug-toggle-source-breakpoint "/test.rb" 11) + (assert-equal "delete 2" last-gud-call) + + ;; ---------- + ;; Toggle enable/disable. + + ;; Add new. + (rdebug-toggle-source-breakpoint-enabled "/test.rb" 30) + (assert-equal "break /test.rb:30" last-gud-call) + + ;; Toggle enabled. + (rdebug-toggle-source-breakpoint-enabled "/test.rb" 10) + (assert-equal "disable 1" last-gud-call) + ;; Toggle disabled. + (rdebug-toggle-source-breakpoint-enabled "/test.rb" 11) + (assert-equal "enable 2" last-gud-call))) + + +;; ------------------------------------------------------------------- +;; Check rdebug-next with prefix toggling commands +;; +(deftest "rdebug-stepping-test" + (setq rdebug-stepping-prefix "") + (assert-equal "next 1" (rdebug-next)) + (setq rdebug-stepping-prefix "-") + (assert-equal "next- 2" (rdebug-next 2)) + (setq rdebug-stepping-prefix "+") + (assert-equal "step+ 1" (rdebug-step)) + ) + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-cmd-suite" + "rdebug-goto-frame-test" + "rdebug-stepping-test" + "rdebug-toggle-breakpoints") +(run-elk-test "rdebug-cmd-suite" + "test some rdebug-core code") diff --git a/emacs/test/test-core.el b/emacs/test/test-core.el new file mode 100644 index 0000000..206b60a --- /dev/null +++ b/emacs/test/test-core.el @@ -0,0 +1,104 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(load-file "../rdebug.el") +(load-file "../rdebug-core.el") + +;; Redefine functions to make them harmless for testing +(defun rdebug-process-annotation (name contents) + (message name) + ) + +(make-variable-buffer-local 'gud-rdebug-marker-acc) + +(deftest "rdebug-get-script-name-test" + (assert-equal '("foo" nil) (rdebug-get-script-name '("rdebug" "foo"))) + (assert-equal '("foo" nil) (rdebug-get-script-name '("rdebug" "-m" "foo"))) + (assert-equal '("foo" t) (rdebug-get-script-name + '("rdebug" "--emacs" "3" "foo"))) + (assert-equal '("foo" t) (rdebug-get-script-name + '("myrdebug" "--annotate=1" "foo"))) + (assert-equal '("foo" t) (rdebug-get-script-name + '("ruby" "rdebug" "--annotate" "1" "foo"))) + (assert-equal '("foo" nil) (rdebug-get-script-name + '("/usr/bin/ruby19" "rdebug" "--emacs-basic" "foo"))) + (assert-equal '("foo" nil) (rdebug-get-script-name + '("rdbg.rb" "foo"))) + (assert-equal '("rdbg.rb" nil) (rdebug-get-script-name + '("rdebug" "rdbg.rb" "foo"))) + (assert-equal '("foo" t) (rdebug-get-script-name '("rdebug" "-A" "1" "foo"))) + (assert-equal '("foo" nil) + (rdebug-get-script-name + '("rdebug" "--include" "me" "-n" "foo"))) + (assert-equal '("foo" nil) (rdebug-get-script-name + '("rdebug" "--server" "-d" "--host" + "localhost" "foo" "-1"))) + ) + +(deftest "rdebug-goto-entry-test" + (let ((buf (generate-new-buffer "testing"))) + (save-excursion + (switch-to-buffer buf) + (insert "#0 at line /tmp/gcd.rb:4\n") + (goto-char (point-min)) + (assert-equal t (rdebug-goto-entry-try "0")) + (assert-equal nil (rdebug-goto-entry-try "1")) + (insert " 1 y at gcd.rb:10\n") + (goto-char (point-min)) + ;; Don't know why this doesn't work. + ;;(assert-equal t (rdebug-goto-entry-try "1")) + (insert "5: 1 + 2 = 3\n") + (goto-char (point-min)) + (assert-equal t (rdebug-goto-entry-try "5")) + (goto-char (point-min)) + (assert-equal nil (rdebug-goto-entry-try "3"))) + (kill-buffer buf))) + +(defun rdebug-test-call-entry-n (str) + "Call `rdebug-goto-entry-n', return the line we landed on." + (rdebug-goto-entry-n-internal str) + (beginning-of-line) + (count-lines (point-min) (point))) + +;; The original implementation could not go to "10" if there was no "1" entry. +(deftest "rdebug-goto-entry-test-2" + (let ((buf (generate-new-buffer "testing"))) + (save-excursion + (switch-to-buffer buf) + (insert "#0 at line /tmp/gcd.rb:4\n") + (insert "#2 at line /tmp/gcd.rb:44\n") + (insert "#13 at line /tmp/gcd.rb:444\n") + (goto-char (point-min)) + (setq rdebug-goto-entry-acc "") + ;; Goto "0" + (assert-equal 0 (rdebug-test-call-entry-n "0")) + ;; Goto "2" + (assert-equal 1 (rdebug-test-call-entry-n "2")) + ;; There is no "1" or "21" or "021", so stay. + (assert-equal 1 (rdebug-test-call-entry-n "1")) + ;; Goto "13" + (assert-equal 2 (rdebug-test-call-entry-n "3")) + ;; There is no "5", "35", or "135", so stay. + (assert-equal 2 (rdebug-test-call-entry-n "5")) + ;; Goto "0" + (assert-equal 0 (rdebug-test-call-entry-n "0")) + ;; Goto "2" + (assert-equal 1 (rdebug-test-call-entry-n "2"))) + (kill-buffer buf))) + + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-get-script-name-test" + "rdebug-goto-entry-test" + "rdebug-goto-entry-test-2") +(run-elk-test "rdebug-suite" + "test things in rdebug-core.el") + diff --git a/emacs/test/test-fns.el b/emacs/test/test-fns.el new file mode 100644 index 0000000..89341cf --- /dev/null +++ b/emacs/test/test-fns.el @@ -0,0 +1,65 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +(setq load-path (cons ".." load-path)) +(require 'rdebug-fns) +(require 'rdebug-locring) +(setq load-path (cdr load-path)) + +;; ------------------------------------------------------------------- + +(deftest "test-add-to-ring" + (let ((location-ring (make-ring 5))) + (assert-equal t (ring-empty-p location-ring)) + (rdebug-locring-add 'first location-ring) + (assert-equal 'first (ring-ref location-ring 0)) + (assert-equal 1 (ring-length location-ring)) + ;; Trying to add the same entry should not again. + (rdebug-locring-add 'first location-ring) + (assert-equal 1 (ring-length location-ring)) + + ;; Second should go in as last item. + (rdebug-locring-add 'second location-ring) + (assert-equal 'second (ring-ref location-ring 1)) + ;; First item is still 0. + (assert-equal 'first (ring-ref location-ring 0)))) + +(deftest "test-chomp" + (assert-equal "" (chomp "")) + (assert-equal "hi" (chomp "hi")) + (assert-equal "hi" (chomp "hi\n")) + (assert-equal "hi\n" (chomp "hi\n\n")) + (assert-equal "hi" (chomp "hi\n\n" t))) + +(deftest "test-set-frame-arrow" + (let ((rdebug-frames-current-frame-number 0)) + (rdebug-set-frame-arrow (current-buffer)) + (assert-equal '((overlay-arrow . right-triangle)) + fringe-indicator-alist) + (setq rdebug-frames-current-frame-number 1) + (rdebug-set-frame-arrow (current-buffer)) + (assert-equal '((overlay-arrow . hollow-right-triangle)) + fringe-indicator-alist))) + +(require 'shell) +(deftest "test-dead-process-p" + (assert-equal t (rdebug-dead-process-p)) + (let ((gud-comint-buffer nil)) + (assert-equal t (rdebug-dead-process-p)) + (setq gud-comint-buffer (shell)) + (assert-equal nil (rdebug-dead-process-p)))) + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-gud-suite" + "test-add-to-ring" + "test-chomp" + "test-dead-process-p" + "test-set-frame-arrow") + +(run-elk-test "rdebug-gud-suite" + "test some rdebug-error code") diff --git a/emacs/test/test-frames.el b/emacs/test/test-frames.el new file mode 100644 index 0000000..c491f75 --- /dev/null +++ b/emacs/test/test-frames.el @@ -0,0 +1,62 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(load-file "../rdebug.el") +(load-file "../rdebug-regexp.el") +(load-file "../rdebug-frames.el") + +(make-variable-buffer-local 'gud-rdebug-marker-acc) + +(deftest "rdebug-stack-buffer-field-test" + (let ((buf (generate-new-buffer "testing"))) + (save-excursion + (switch-to-buffer buf) + (insert + "--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line /tmp/gcd.rb:4\n") + (insert + " at line /foo/bar/custom_require.rb:27\n") + + (goto-char (point-min)) + (let* ((b (line-beginning-position)) (e (line-end-position)) + (s (buffer-substring b e)) + (file nil) (line nil)) + (assert-nonnil (string-match rdebug-stack-frame-regexp s)) + (assert-equal "/tmp/gcd.rb" (rdebug-stack-buffer-field + s b + rdebug-stack-frame-file-group + font-lock-comment-face)) + (assert-equal "4" (rdebug-stack-buffer-field + s b + rdebug-stack-frame-line-group + font-lock-constant-face)) + (forward-line) + (setq b (line-beginning-position)) + (setq e (line-end-position)) + (setq s (buffer-substring b e)) + (assert-nonnil (string-match rdebug-stack-frame-2nd-regexp s)) + (assert-equal "/foo/bar/custom_require.rb" + (rdebug-stack-buffer-field + s b + rdebug-stack-frame-2nd-file-group + font-lock-comment-face)) + (assert-equal "27" (rdebug-stack-buffer-field + s b + rdebug-stack-frame-2nd-line-group + font-lock-constant-face)) + )) + (kill-buffer buf))) + + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-stack-buffer-field-test") +(run-elk-test "rdebug-suite" + "test things in rdebug-frames.el") + diff --git a/emacs/test/test-gud.el b/emacs/test/test-gud.el new file mode 100644 index 0000000..ddf3c39 --- /dev/null +++ b/emacs/test/test-gud.el @@ -0,0 +1,35 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +(setq load-path (cons ".." load-path)) +(require 'rdebug-gud) +(setq load-path (cdr load-path)) + +(defun y-or-n-p (prompt) + "Replacement of y-or-n-p() for rdebug testing" + (assert-nil "y-or-n-p should not have been called")) + +(defun error (msg) + "Replacement error() for rdebug testing" + (assert-nil "error should not have been called")) + +;; ------------------------------------------------------------------- + +(deftest "test-rdebug-find-file" + ;; Set to cause a warning in find-file-no-select and + ;; check that it is ignored. + (let ((large-file-warning-threshold 1)) + (gud-rdebug-find-file "elk-test.el"))) + + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-gud-suite" + "test-rdebug-find-file") + +(run-elk-test "rdebug-gud-suite" + "test some rdebug-gud code") diff --git a/emacs/test/test-indent.el b/emacs/test/test-indent.el new file mode 100644 index 0000000..ad4ec91 --- /dev/null +++ b/emacs/test/test-indent.el @@ -0,0 +1,58 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; ------------------------------------------------------------------- +;; Check source code indentation +;; + +(put 'rdebug-debug-enter 'lisp-indent-hook 1) + +(defun rdebug-test-reindent-one-file (file) + (let ((buf (generate-new-buffer "testing")) + (res nil)) + (save-excursion + (switch-to-buffer buf) + (insert-file file) + (emacs-lisp-mode) + (set-buffer-modified-p nil) + (undo-boundary) + (indent-region (point-min) (point-max)) + (if (buffer-modified-p) + (setq res "Reindentation failed"))) + (kill-buffer buf) + res)) + +(deftest "rdebug-indent-files" + (mapcar (lambda (lisp-file) + (message lisp-file) + (assert-nil (rdebug-test-reindent-one-file lisp-file))) + '("../rdebug.el" + "../rdebug-breaks.el" + "../rdebug-cmd.el" + "../rdebug-core.el" + "../rdebug-dbg.el" + "../rdebug-error.el" + "../rdebug-frames.el" + "../rdebug-fns.el" + "../rdebug-gud.el" + "../rdebug-help.el" + "../rdebug-info.el" + "../rdebug-layouts.el" + "../rdebug-output.el" + "../rdebug-regexp.el" + "../rdebug-secondary.el" + "../rdebug-source.el" + "../rdebug-track.el" + "../rdebug-varbuf.el" + "../rdebug-vars.el" + "../rdebug-watch.el" + "./test-cmd.el" + "./test-core.el" + "./test-indent.el" + "./test-regexp.el" + ))) + +(run-elk-test "rdebug-indent-files" + "test indentation of Lisp files") diff --git a/emacs/test/test-regexp.el b/emacs/test/test-regexp.el new file mode 100644 index 0000000..790971e --- /dev/null +++ b/emacs/test/test-regexp.el @@ -0,0 +1,144 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(load-file "../rdebug.el") +(load-file "../rdebug-core.el") + +(make-variable-buffer-local 'gud-rdebug-marker-acc) + +(defun regexp-breakpoint-test (location-str pos-str enabled-str file-str line-str) + "Test to see that location-str parses rdebug-breakpoint-regexp properly" + (assert-equal 0 (string-match rdebug-breakpoint-regexp location-str)) + (assert-equal pos-str + (substring location-str (match-beginning 1) (match-end 1))) + (assert-equal enabled-str + (substring location-str (match-beginning 2) (match-end 2))) + (assert-equal file-str + (substring location-str (match-beginning 3) (match-end 3))) + (assert-equal line-str + (substring location-str (match-beginning 4) (match-end 4))) + ) +(deftest "rdebug-regexp-breakpoint-test" + + (regexp-breakpoint-test + " 1 y at gcd.rb:6" + "1" "y" "gcd.rb" "6" + ) + (regexp-breakpoint-test + " 1 y at gcd.rb:6 if 1 == a" + "1" "y" "gcd.rb" "6" + ) + ) + +(defun regexp-file-test (location-str file-str) + "Test to see that location-str matches gud-rdebug-marker-regexp" + (assert-equal 0 (string-match gud-rdebug-marker-regexp location-str)) + (assert-equal file-str + (substring location-str (match-beginning 1) (match-end 1))) + ) +(deftest "rdebug-regexp-file-test" + + (regexp-file-test + "\032\032./hanoi.rb:3\n" + "./hanoi.rb" + ) + (regexp-file-test + "\032\032source ./hanoi.rb:3\n" + "./hanoi.rb" + ) + (regexp-file-test + "\032\032C:/tmp/gcd.rb:29\n" + "C:/tmp/gcd.rb" + ) + (regexp-file-test + "\032\032source \\sources\\capfilterscanner\\capanalyzer.rb:3: \n" + "\\sources\\capfilterscanner\\capanalyzer.rb" + ) + ) + +(deftest "rdebug-regexp-marker-filter-test" + (assert-equal "Testing 1 2 3" (gud-rdebug-marker-filter "Testing 1 2 3")) + (assert-equal "ABC" (gud-rdebug-marker-filter + "\ +breakpoints +No breakpoints + +ABC"))) + +(defun regexp-stack-test (location-str pos-str file-str line-str) + "Test to see that location-str parses rdebug-stack-frame-regexp properly" + (assert-equal 0 (string-match rdebug-stack-frame-regexp location-str)) + (assert-equal pos-str + (substring location-str (match-beginning 2) (match-end 2))) + (assert-equal file-str + (substring location-str (match-beginning 4) (match-end 4))) + (assert-equal line-str + (substring location-str (match-beginning 5) (match-end 5))) + ) +(deftest "rdebug-regexp-stack-test" + + (regexp-stack-test + "--> #0 at line /home/rocky/ruby/gcd.rb:18" + "0" "/home/rocky/ruby/gcd.rb" "18" + ) + ) + +(defun regexp-traceback-test (location-str file-str line-str) + "Test to see that location-str matches position-regexp-file-test with the correct +file and line submatches." + (assert-equal 0 (string-match rdebug-traceback-line-re location-str)) + (assert-equal file-str (match-string 1 location-str)) + (assert-equal line-str (match-string 2 location-str)) + ) + +(deftest "rdebug-regexp-traceback-test" + + (regexp-traceback-test + " from /home/rocky/ruby/gcd.rb:15:in `gcd'" + "/home/rocky/ruby/gcd.rb" "15" + ) + (regexp-traceback-test + " from /home/rocky/ruby/gcd.rb:19" + "/home/rocky/ruby/gcd.rb" "19" + ) + ) + +(defun regexp-unittest-traceback-test (location-str file-str line-str) + "Test to see that location-str matches position-regexp-file-test with the correct +file and line submatches." + (assert-equal 0 (string-match rdebug-dollarbang-traceback-line-re + location-str)) + (assert-equal file-str (match-string 1 location-str)) + (assert-equal line-str (match-string 2 location-str)) + ) + +(deftest "rdebug-regexp-unittest-traceback-test" + + (regexp-unittest-traceback-test + " [test-frame.rb:26:in `test_basic'" + "test-frame.rb" "26" + ) + (regexp-unittest-traceback-test + " test-frame.rb:22:in `test_basic']:" + "test-frame.rb" "22" + ) + ) + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-regexp-breakpoint-test" + "rdebug-regexp-file-test" + "rdebug-regexp-marker-filter-test" + "rdebug-regexp-stack-test" + "rdebug-regexp-traceback-test" + "rdebug-regexp-unittest-traceback-test") + +(run-elk-test "rdebug-suite" + "test regular expressions used in tracking lines") diff --git a/emacs/test/test-shortkey.el b/emacs/test/test-shortkey.el new file mode 100644 index 0000000..3318c40 --- /dev/null +++ b/emacs/test/test-shortkey.el @@ -0,0 +1,61 @@ +;; -*- emacs-lisp -*- +;; This program has to be run from the directory it is currently in and +;; the rdebug code has to be in the parent directory +(load-file "./elk-test.el") + +;; FIXME? Should we use "require 'rdebug" here. +;; Would have to prepend . to load-path. +(setq load-path (cons ".." load-path)) +(load-file "../rdebug-shortkey.el") + +(deftest "rdebug-shortkey-mode-test" + (let ((buf (generate-new-buffer "shortkey readwrite"))) + (with-current-buffer buf + (setq buffer-read-only nil) + ;; turning on short-key-mode make buffer read-only + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + ;; turning off short-key-mode should make buffer read-write again + (rdebug-internal-short-key-mode -1) + (assert-equal nil buffer-read-only) + + ;; -------------------- + ;; Check multiple "on": and "off:s". + + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + (rdebug-internal-short-key-mode -1) + (assert-equal nil buffer-read-only)) + + (kill-buffer buf)) + + (let ((buf (generate-new-buffer "shortkey readonly"))) + (with-current-buffer buf + (setq buffer-read-only t) + + ;; turning on short-key-mode keep buffer read-only + (rdebug-internal-short-key-mode 1) + (assert-equal t buffer-read-only) + + ;; The buffer was originally in read-only mode, it should remain + ;; there. + (rdebug-internal-short-key-mode -1) + (assert-equal t buffer-read-only)) + (kill-buffer buf))) + +;; ------------------------------------------------------------------- +;; Build and run the test suite. +;; + +(build-suite "rdebug-suite" + "rdebug-shortkey-mode-test") +(run-elk-test "rdebug-suite" + "test things in rdebug-shortkey.el") diff --git a/ext/.svn/README.txt b/ext/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/ext/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/ext/.svn/dir-prop-base b/ext/.svn/dir-prop-base new file mode 100644 index 0000000..58d2b2e --- /dev/null +++ b/ext/.svn/dir-prop-base @@ -0,0 +1,8 @@ +K 10 +svn:ignore +V 34 +.cvsignore +ruby_debug.so +Makefile + +END diff --git a/ext/.svn/dir-props b/ext/.svn/dir-props new file mode 100644 index 0000000..58d2b2e --- /dev/null +++ b/ext/.svn/dir-props @@ -0,0 +1,8 @@ +K 10 +svn:ignore +V 34 +.cvsignore +ruby_debug.so +Makefile + +END diff --git a/ext/.svn/empty-file b/ext/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/ext/.svn/entries b/ext/.svn/entries new file mode 100644 index 0000000..f163ea7 --- /dev/null +++ b/ext/.svn/entries @@ -0,0 +1,53 @@ + + + + + + + + + diff --git a/ext/.svn/format b/ext/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/ext/.svn/format @@ -0,0 +1 @@ +4 diff --git a/ext/.svn/prop-base/breakpoint.c.svn-base b/ext/.svn/prop-base/breakpoint.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/.svn/prop-base/breakpoint.c.svn-base @@ -0,0 +1 @@ +END diff --git a/ext/.svn/prop-base/extconf.rb.svn-base b/ext/.svn/prop-base/extconf.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/.svn/prop-base/extconf.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/ext/.svn/prop-base/ruby_debug.c.svn-base b/ext/.svn/prop-base/ruby_debug.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/.svn/prop-base/ruby_debug.c.svn-base @@ -0,0 +1 @@ +END diff --git a/ext/.svn/prop-base/ruby_debug.h.svn-base b/ext/.svn/prop-base/ruby_debug.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/.svn/prop-base/ruby_debug.h.svn-base @@ -0,0 +1 @@ +END diff --git a/ext/.svn/props/breakpoint.c.svn-work b/ext/.svn/props/breakpoint.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/.svn/props/breakpoint.c.svn-work @@ -0,0 +1 @@ +END diff --git a/ext/.svn/props/extconf.rb.svn-work b/ext/.svn/props/extconf.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/.svn/props/extconf.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/ext/.svn/props/ruby_debug.c.svn-work b/ext/.svn/props/ruby_debug.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/.svn/props/ruby_debug.c.svn-work @@ -0,0 +1 @@ +END diff --git a/ext/.svn/props/ruby_debug.h.svn-work b/ext/.svn/props/ruby_debug.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/.svn/props/ruby_debug.h.svn-work @@ -0,0 +1 @@ +END diff --git a/ext/.svn/text-base/breakpoint.c.svn-base b/ext/.svn/text-base/breakpoint.c.svn-base new file mode 100644 index 0000000..d3b7b78 --- /dev/null +++ b/ext/.svn/text-base/breakpoint.c.svn-base @@ -0,0 +1,579 @@ +#include "ruby_debug.h" + +VALUE rdebug_breakpoints = Qnil; +VALUE rdebug_catchpoints; + +static VALUE cBreakpoint; +static ID idEval; + +static VALUE +eval_expression(VALUE args) +{ + return rb_funcall2(rb_mKernel, idEval, 2, RARRAY(args)->ptr); +} + +int +check_breakpoint_hit_condition(VALUE breakpoint) +{ + debug_breakpoint_t *debug_breakpoint; + + if(breakpoint == Qnil) + return 0; + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + + debug_breakpoint->hit_count++; + if (!Qtrue == debug_breakpoint->enabled) return 0; + switch(debug_breakpoint->hit_condition) + { + case HIT_COND_NONE: + return 1; + case HIT_COND_GE: + { + if(debug_breakpoint->hit_count >= debug_breakpoint->hit_value) + return 1; + break; + } + case HIT_COND_EQ: + { + if(debug_breakpoint->hit_count == debug_breakpoint->hit_value) + return 1; + break; + } + case HIT_COND_MOD: + { + if(debug_breakpoint->hit_count % debug_breakpoint->hit_value == 0) + return 1; + break; + } + } + return 0; +} + +static int +check_breakpoint_by_pos(VALUE breakpoint, char *file, int line) +{ + debug_breakpoint_t *debug_breakpoint; + + if(breakpoint == Qnil) + return 0; + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + if (!Qtrue == debug_breakpoint->enabled) return 0; + if(debug_breakpoint->type != BP_POS_TYPE) + return 0; + if(debug_breakpoint->pos.line != line) + return 0; + if(filename_cmp(debug_breakpoint->source, file)) + return 1; + return 0; +} + +int +check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid) +{ + debug_breakpoint_t *debug_breakpoint; + + if(breakpoint == Qnil) + return 0; + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + if (!Qtrue == debug_breakpoint->enabled) return 0; + if(debug_breakpoint->type != BP_METHOD_TYPE) + return 0; + if(debug_breakpoint->pos.mid != mid) + return 0; + if(classname_cmp(debug_breakpoint->source, klass)) + return 1; + return 0; +} + +VALUE +check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line) +{ + VALUE breakpoint; + int i; + + if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT)) + return Qnil; + + if(check_breakpoint_by_pos(debug_context->breakpoint, file, line)) + return debug_context->breakpoint; + + if(RARRAY(rdebug_breakpoints)->len == 0) + return Qnil; + for(i = 0; i < RARRAY(rdebug_breakpoints)->len; i++) + { + breakpoint = rb_ary_entry(rdebug_breakpoints, i); + if(check_breakpoint_by_pos(breakpoint, file, line)) + return breakpoint; + } + return Qnil; +} + +VALUE +check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid) +{ + VALUE breakpoint; + int i; + + if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT)) + return Qnil; + + if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid)) + return debug_context->breakpoint; + + if(RARRAY(rdebug_breakpoints)->len == 0) + return Qnil; + for(i = 0; i < RARRAY(rdebug_breakpoints)->len; i++) + { + breakpoint = rb_ary_entry(rdebug_breakpoints, i); + if(check_breakpoint_by_method(breakpoint, klass, mid)) + return breakpoint; + } + return Qnil; +} + +int +check_breakpoint_expression(VALUE breakpoint, VALUE binding) +{ + debug_breakpoint_t *debug_breakpoint; + VALUE args, expr_result; + + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + if(NIL_P(debug_breakpoint->expr)) + return 1; + + args = rb_ary_new3(2, debug_breakpoint->expr, binding); + expr_result = rb_protect(eval_expression, args, 0); + return RTEST(expr_result); +} + +static void +breakpoint_mark(void *data) +{ + debug_breakpoint_t *breakpoint; + breakpoint = (debug_breakpoint_t *)data; + rb_gc_mark(breakpoint->source); + rb_gc_mark(breakpoint->expr); +} + +VALUE +create_breakpoint_from_args(int argc, VALUE *argv, int id) +{ + VALUE source, pos, expr; + debug_breakpoint_t *breakpoint; + int type; + + if(rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2) + { + expr = Qnil; + } + type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE; + if(type == BP_POS_TYPE) + source = StringValue(source); + else + pos = StringValue(pos); + breakpoint = ALLOC(debug_breakpoint_t); + breakpoint->id = id; + breakpoint->source = source; + breakpoint->type = type; + if(type == BP_POS_TYPE) + breakpoint->pos.line = FIX2INT(pos); + else + breakpoint->pos.mid = rb_intern(RSTRING(pos)->ptr); + breakpoint->enabled = Qtrue; + breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr); + breakpoint->hit_count = 0; + breakpoint->hit_value = 0; + breakpoint->hit_condition = HIT_COND_NONE; + return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint); +} + +/* + * call-seq: + * Debugger.remove_breakpoint(id) -> breakpoint + * + * Removes breakpoint by its id. + * id is an identificator of a breakpoint. + */ +VALUE +rdebug_remove_breakpoint(VALUE self, VALUE id_value) +{ + int i; + int id; + VALUE breakpoint; + debug_breakpoint_t *debug_breakpoint; + + id = FIX2INT(id_value); + + for( i = 0; i < RARRAY(rdebug_breakpoints)->len; i += 1 ) + { + breakpoint = rb_ary_entry(rdebug_breakpoints, i); + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + if(debug_breakpoint->id == id) + { + rb_ary_delete_at(rdebug_breakpoints, i); + return breakpoint; + } + } + return Qnil; +} + +/* + * call-seq: + * Debugger.catchpoints -> hash + * + * Returns a current catchpoints, which is a hash exception names that will + * trigger a debugger when raised. The values are the number of times taht + * catchpoint was hit, initially 0. + */ +VALUE +debug_catchpoints(VALUE self) +{ + debug_check_started(); + + return rdebug_catchpoints; +} + +/* + * call-seq: + * Debugger.catchpoint(string) -> string + * + * Sets catchpoint. Returns the string passed. + */ +VALUE +rdebug_add_catchpoint(VALUE self, VALUE value) +{ + debug_check_started(); + + if (TYPE(value) != T_STRING) { + rb_raise(rb_eTypeError, "value of a catchpoint must be String"); + } + rb_hash_aset(rdebug_catchpoints, rb_str_dup(value), INT2FIX(0)); + return value; +} + +/* + * call-seq: + * context.breakpoint -> breakpoint + * + * Returns a context-specific temporary Breakpoint object. + */ +VALUE +context_breakpoint(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return debug_context->breakpoint; +} + +/* + * call-seq: + * context.set_breakpoint(source, pos, condition = nil) -> breakpoint + * + * Sets a context-specific temporary breakpoint, which can be used to implement + * 'Run to Cursor' debugger function. When this breakpoint is reached, it will be + * cleared out. + * + * source is a name of a file or a class. + * pos is a line number or a method name if source is a class name. + * condition is a string which is evaluated to +true+ when this breakpoint + * is activated. + */ +VALUE +context_set_breakpoint(int argc, VALUE *argv, VALUE self) +{ + VALUE result; + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + result = create_breakpoint_from_args(argc, argv, 0); + debug_context->breakpoint = result; + return result; +} + +/* + * call-seq: + * breakpoint.enabled? + * + * Returns whether breakpoint is enabled or not. + */ +static VALUE +breakpoint_enabled(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return breakpoint->enabled; +} + +/* + * call-seq: + * breakpoint.enabled = bool + * + * Enables or disables breakpoint. + */ +static VALUE +breakpoint_set_enabled(VALUE self, VALUE bool) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return breakpoint->enabled = bool; +} + +/* + * call-seq: + * breakpoint.source -> string + * + * Returns a source of the breakpoint. + */ +static VALUE +breakpoint_source(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return breakpoint->source; +} + +/* + * call-seq: + * breakpoint.source = string + * + * Sets the source of the breakpoint. + */ +static VALUE +breakpoint_set_source(VALUE self, VALUE value) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + breakpoint->source = StringValue(value); + return value; +} + +/* + * call-seq: + * breakpoint.pos -> string or int + * + * Returns the position of this breakpoint. + */ +static VALUE +breakpoint_pos(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + if(breakpoint->type == BP_METHOD_TYPE) + return rb_str_new2(rb_id2name(breakpoint->pos.mid)); + else + return INT2FIX(breakpoint->pos.line); +} + +/* + * call-seq: + * breakpoint.pos = string or int + * + * Sets the position of this breakpoint. + */ +static VALUE +breakpoint_set_pos(VALUE self, VALUE value) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + if(breakpoint->type == BP_METHOD_TYPE) + { + breakpoint->pos.mid = rb_to_id(StringValue(value)); + } + else + breakpoint->pos.line = FIX2INT(value); + return value; +} + +/* + * call-seq: + * breakpoint.expr -> string + * + * Returns a codition expression when this breakpoint should be activated. + */ +static VALUE +breakpoint_expr(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return breakpoint->expr; +} + +/* + * call-seq: + * breakpoint.expr = string | nil + * + * Sets the codition expression when this breakpoint should be activated. + */ +static VALUE +breakpoint_set_expr(VALUE self, VALUE expr) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr); + return expr; +} + +/* + * call-seq: + * breakpoint.id -> int + * + * Returns id of the breakpoint. + */ +static VALUE +breakpoint_id(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return INT2FIX(breakpoint->id); +} + +/* + * call-seq: + * breakpoint.hit_count -> int + * + * Returns the hit count of the breakpoint. + */ +static VALUE +breakpoint_hit_count(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return INT2FIX(breakpoint->hit_count); +} + +/* + * call-seq: + * breakpoint.hit_value -> int + * + * Returns the hit value of the breakpoint. + */ +static VALUE +breakpoint_hit_value(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return INT2FIX(breakpoint->hit_value); +} + +/* + * call-seq: + * breakpoint.hit_value = int + * + * Sets the hit value of the breakpoint. + */ +static VALUE +breakpoint_set_hit_value(VALUE self, VALUE value) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + breakpoint->hit_value = FIX2INT(value); + return value; +} + +/* + * call-seq: + * breakpoint.hit_condition -> symbol + * + * Returns the hit condition of the breakpoint: + * + * +nil+ if it is an unconditional breakpoint, or + * :greater_or_equal, :equal, :modulo + */ +static VALUE +breakpoint_hit_condition(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + switch(breakpoint->hit_condition) + { + case HIT_COND_GE: + return ID2SYM(rb_intern("greater_or_equal")); + case HIT_COND_EQ: + return ID2SYM(rb_intern("equal")); + case HIT_COND_MOD: + return ID2SYM(rb_intern("modulo")); + case HIT_COND_NONE: + default: + return Qnil; + } +} + +/* + * call-seq: + * breakpoint.hit_condition = symbol + * + * Sets the hit condition of the breakpoint which must be one of the following values: + * + * +nil+ if it is an unconditional breakpoint, or + * :greater_or_equal(:ge), :equal(:eq), :modulo(:mod) + */ +static VALUE +breakpoint_set_hit_condition(VALUE self, VALUE value) +{ + debug_breakpoint_t *breakpoint; + ID id_value; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + id_value = rb_to_id(value); + + if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value) + breakpoint->hit_condition = HIT_COND_GE; + else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value) + breakpoint->hit_condition = HIT_COND_EQ; + else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value) + breakpoint->hit_condition = HIT_COND_MOD; + else + rb_raise(rb_eArgError, "Invalid condition parameter"); + return value; +} + +/* + * Document-class: Breakpoint + * + * == Summary + * + * This class represents a breakpoint. It defines position of the breakpoint and + * condition when this breakpoint should be triggered. + */ +void +Init_breakpoint() +{ + cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject); + rb_define_method(cBreakpoint, "enabled=", breakpoint_set_enabled, 1); + rb_define_method(cBreakpoint, "enabled?", breakpoint_enabled, 0); + rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0); + rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1); + rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0); + rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1); + rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0); + rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0); + rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1); + rb_define_method(cBreakpoint, "id", breakpoint_id, 0); + rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0); + rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1); + rb_define_method(cBreakpoint, "source", breakpoint_source, 0); + rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1); + idEval = rb_intern("eval"); + rdebug_catchpoints = rb_hash_new(); + +} + + diff --git a/ext/.svn/text-base/extconf.rb.svn-base b/ext/.svn/text-base/extconf.rb.svn-base new file mode 100644 index 0000000..1bb8e40 --- /dev/null +++ b/ext/.svn/text-base/extconf.rb.svn-base @@ -0,0 +1,20 @@ +require "mkmf" + +if RUBY_VERSION >= "1.9" + if RUBY_RELEASE_DATE < "2005-03-17" + STDERR.print("Ruby version is too old\n") + exit(1) + end +elsif RUBY_VERSION >= "1.8" + if RUBY_RELEASE_DATE < "2005-03-22" + STDERR.print("Ruby version is too old\n") + exit(1) + end +else + STDERR.print("Ruby version is too old\n") + exit(1) +end + +# Temporary: to turn off optimization +# $CFLAGS='-fno-strict-aliasing -g -fPIC' +create_makefile("ruby_debug") diff --git a/ext/.svn/text-base/ruby_debug.c.svn-base b/ext/.svn/text-base/ruby_debug.c.svn-base new file mode 100644 index 0000000..503329a --- /dev/null +++ b/ext/.svn/text-base/ruby_debug.c.svn-base @@ -0,0 +1,2322 @@ +#include "ruby_debug.h" + +#include +#include +#include +#include +#include + +#define DEBUG_VERSION "0.10.4" + + +#ifdef _WIN32 +struct FRAME { + VALUE self; + int argc; + ID last_func; + ID orig_func; + VALUE last_class; + struct FRAME *prev; + struct FRAME *tmp; + struct RNode *node; + int iter; + int flags; + unsigned long uniq; +}; + +struct SCOPE { + struct RBasic super; + ID *local_tbl; + VALUE *local_vars; + int flags; +}; + +struct RVarmap { + struct RBasic super; + ID id; + VALUE val; + struct RVarmap *next; +}; + +RUBY_EXTERN struct SCOPE *ruby_scope; +RUBY_EXTERN struct FRAME *ruby_frame; +RUBY_EXTERN struct RVarmap *ruby_dyna_vars; +#else +#include +#endif + +#define FRAME_N(n) (&debug_context->frames[debug_context->stack_size-(n)-1]) +#define GET_FRAME (FRAME_N(check_frame_number(debug_context, frame))) + +#ifndef min +#define min(x,y) ((x) < (y) ? (x) : (y)) +#endif + +#define STACK_SIZE_INCREMENT 128 + +typedef struct { + st_table *tbl; +} threads_table_t; + +static VALUE tracing = Qfalse; +static VALUE locker = Qnil; +static VALUE post_mortem = Qfalse; +static VALUE keep_frame_binding = Qfalse; +static VALUE debug = Qfalse; +static VALUE track_frame_args = Qfalse; + +static VALUE last_context = Qnil; +static VALUE last_thread = Qnil; +static debug_context_t *last_debug_context = NULL; + +VALUE rdebug_threads_tbl = Qnil; /* Context for each of the threads */ +VALUE mDebugger; /* Ruby Debugger Module object */ + +static VALUE cThreadsTable; +static VALUE cContext; +static VALUE cDebugThread; + +static VALUE rb_mObjectSpace; + +static ID idAtBreakpoint; +static ID idAtCatchpoint; +static ID idAtLine; +static ID idAtReturn; +static ID idAtTracing; +static ID idList; + +static int start_count = 0; +static int thnum_max = 0; +static int bkp_count = 0; +static int last_debugged_thnum = -1; +static unsigned long last_check = 0; +static unsigned long hook_count = 0; + +static VALUE create_binding(VALUE); +static VALUE debug_stop(VALUE); +static void save_current_position(debug_context_t *); +static VALUE context_copy_args(debug_frame_t *); +static VALUE context_copy_locals(debug_frame_t *); +static void context_suspend_0(debug_context_t *); +static void context_resume_0(debug_context_t *); +static void copy_scalar_args(debug_frame_t *); + +typedef struct locked_thread_t { + VALUE thread_id; + struct locked_thread_t *next; +} locked_thread_t; + +static locked_thread_t *locked_head = NULL; +static locked_thread_t *locked_tail = NULL; + +/* "Step", "Next" and "Finish" do their work by saving information + about where to stop next. reset_stopping_points removes/resets this + information. */ +inline static void +reset_stepping_stop_points(debug_context_t *debug_context) +{ + debug_context->dest_frame = -1; + debug_context->stop_line = -1; + debug_context->stop_next = -1; +} + +inline static VALUE +real_class(VALUE klass) +{ + if (klass) { + if (TYPE(klass) == T_ICLASS) { + return RBASIC(klass)->klass; + } + else if (FL_TEST(klass, FL_SINGLETON)) { + return rb_iv_get(klass, "__attached__"); + } + } + return klass; +} + +inline static void * +ruby_method_ptr(VALUE class, ID meth_id) +{ + NODE *body, *method; + st_lookup(RCLASS(class)->m_tbl, meth_id, (st_data_t *)&body); + method = (NODE *)body->u2.value; + return (void *)method->u1.value; +} + +inline static VALUE +ref2id(VALUE obj) +{ + return rb_obj_id(obj); +} + +static VALUE +id2ref_unprotected(VALUE id) +{ + typedef VALUE (*id2ref_func_t)(VALUE, VALUE); + static id2ref_func_t f_id2ref = NULL; + if(f_id2ref == NULL) + { + f_id2ref = (id2ref_func_t)ruby_method_ptr(rb_mObjectSpace, rb_intern("_id2ref")); + } + return f_id2ref(rb_mObjectSpace, id); +} + +static VALUE +id2ref_error() +{ + if(debug == Qtrue) + rb_p(ruby_errinfo); + return Qnil; +} + +static VALUE +id2ref(VALUE id) +{ + return rb_rescue(id2ref_unprotected, id, id2ref_error, 0); +} + +inline static VALUE +context_thread_0(debug_context_t *debug_context) +{ + return id2ref(debug_context->thread_id); +} + +static int +is_in_locked(VALUE thread_id) +{ + locked_thread_t *node; + + if(!locked_head) + return 0; + + for(node = locked_head; node != locked_tail; node = node->next) + { + if(node->thread_id == thread_id) return 1; + } + return 0; +} + +static void +add_to_locked(VALUE thread) +{ + locked_thread_t *node; + VALUE thread_id = ref2id(thread); + + if(is_in_locked(thread_id)) + return; + + node = ALLOC(locked_thread_t); + node->thread_id = thread_id; + node->next = NULL; + if(locked_tail) + locked_tail->next = node; + locked_tail = node; + if(!locked_head) + locked_head = node; +} + +static VALUE +remove_from_locked() +{ + VALUE thread; + locked_thread_t *node; + + if(locked_head == NULL) + return Qnil; + node = locked_head; + locked_head = locked_head->next; + if(locked_tail == node) + locked_tail = NULL; + thread = id2ref(node->thread_id); + xfree(node); + return thread; +} + +static int +threads_table_mark_keyvalue(VALUE key, VALUE value, int dummy) +{ + rb_gc_mark(value); + return ST_CONTINUE; +} + +static void +threads_table_mark(void* data) +{ + threads_table_t *threads_table = (threads_table_t*)data; + st_foreach(threads_table->tbl, threads_table_mark_keyvalue, 0); +} + +static void +threads_table_free(void* data) +{ + threads_table_t *threads_table = (threads_table_t*)data; + st_free_table(threads_table->tbl); + xfree(threads_table); +} + +static VALUE +threads_table_create() +{ + threads_table_t *threads_table; + + threads_table = ALLOC(threads_table_t); + threads_table->tbl = st_init_numtable(); + return Data_Wrap_Struct(cThreadsTable, threads_table_mark, threads_table_free, threads_table); +} + +static int +threads_table_clear_i(VALUE key, VALUE value, VALUE dummy) +{ + return ST_DELETE; +} + +static void +threads_table_clear(VALUE table) +{ + threads_table_t *threads_table; + + Data_Get_Struct(table, threads_table_t, threads_table); + st_foreach(threads_table->tbl, threads_table_clear_i, 0); +} + +static VALUE +is_thread_alive(VALUE thread) +{ + typedef VALUE (*thread_alive_func_t)(VALUE); + static thread_alive_func_t f_thread_alive = NULL; + if(!f_thread_alive) + { + f_thread_alive = (thread_alive_func_t)ruby_method_ptr(rb_cThread, rb_intern("alive?")); + } + return f_thread_alive(thread); +} + +static int +threads_table_check_i(VALUE key, VALUE value, VALUE dummy) +{ + VALUE thread; + + thread = id2ref(key); + if(!rb_obj_is_kind_of(thread, rb_cThread)) + { + return ST_DELETE; + } + if(rb_protect(is_thread_alive, thread, 0) != Qtrue) + { + return ST_DELETE; + } + return ST_CONTINUE; +} + +static void +check_thread_contexts() +{ + threads_table_t *threads_table; + + Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table); + st_foreach(threads_table->tbl, threads_table_check_i, 0); +} + +/* + * call-seq: + * Debugger.started? -> bool + * + * Returns +true+ the debugger is started. + */ +static VALUE +debug_is_started(VALUE self) +{ + return IS_STARTED ? Qtrue : Qfalse; +} + +static void +debug_context_mark(void *data) +{ + debug_frame_t *frame; + int i; + + debug_context_t *debug_context = (debug_context_t *)data; + for(i = 0; i < debug_context->stack_size; i++) + { + frame = &(debug_context->frames[i]); + rb_gc_mark(frame->binding); + rb_gc_mark(frame->self); + rb_gc_mark(frame->arg_ary); + if(frame->dead) + { + rb_gc_mark(frame->info.copy.locals); + rb_gc_mark(frame->info.copy.args); + } + } + rb_gc_mark(debug_context->breakpoint); +} + +static void +debug_context_free(void *data) +{ + debug_context_t *debug_context = (debug_context_t *)data; + xfree(debug_context->frames); +} + +static VALUE +debug_context_create(VALUE thread) +{ + debug_context_t *debug_context; + + debug_context = ALLOC(debug_context_t); + debug_context-> thnum = ++thnum_max; + + debug_context->last_file = NULL; + debug_context->last_line = 0; + debug_context->flags = 0; + + debug_context->stop_next = -1; + debug_context->dest_frame = -1; + debug_context->stop_line = -1; + debug_context->stop_frame = -1; + debug_context->stop_reason = CTX_STOP_NONE; + debug_context->stack_len = STACK_SIZE_INCREMENT; + debug_context->frames = ALLOC_N(debug_frame_t, STACK_SIZE_INCREMENT); + debug_context->stack_size = 0; + debug_context->thread_id = ref2id(thread); + debug_context->breakpoint = Qnil; + if(rb_obj_class(thread) == cDebugThread) + CTX_FL_SET(debug_context, CTX_FL_IGNORE); + return Data_Wrap_Struct(cContext, debug_context_mark, debug_context_free, debug_context); +} + +static VALUE +debug_context_dup(debug_context_t *debug_context) +{ + debug_context_t *new_debug_context; + debug_frame_t *new_frame, *old_frame; + int i; + + new_debug_context = ALLOC(debug_context_t); + memcpy(new_debug_context, debug_context, sizeof(debug_context_t)); + new_debug_context->stop_next = -1; + new_debug_context->dest_frame = -1; + new_debug_context->stop_line = -1; + new_debug_context->stop_frame = -1; + new_debug_context->breakpoint = Qnil; + CTX_FL_SET(new_debug_context, CTX_FL_DEAD); + new_debug_context->frames = ALLOC_N(debug_frame_t, debug_context->stack_size); + new_debug_context->stack_len = debug_context->stack_size; + memcpy(new_debug_context->frames, debug_context->frames, sizeof(debug_frame_t) * debug_context->stack_size); + for(i = 0; i < debug_context->stack_size; i++) + { + new_frame = &(new_debug_context->frames[i]); + old_frame = &(debug_context->frames[i]); + new_frame->dead = 1; + new_frame->info.copy.args = context_copy_args(old_frame); + new_frame->info.copy.locals = context_copy_locals(old_frame); + } + return Data_Wrap_Struct(cContext, debug_context_mark, debug_context_free, new_debug_context); +} + +static void +thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_context) +{ + threads_table_t *threads_table; + VALUE thread_id; + debug_context_t *l_debug_context; + + debug_check_started(); + + if(last_thread == thread && last_context != Qnil) + { + *context = last_context; + if(debug_context) + *debug_context = last_debug_context; + return; + } + thread_id = ref2id(thread); + Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table); + if(!st_lookup(threads_table->tbl, thread_id, context)) + { + *context = debug_context_create(thread); + st_insert(threads_table->tbl, thread_id, *context); + } + + Data_Get_Struct(*context, debug_context_t, l_debug_context); + if(debug_context) + *debug_context = l_debug_context; + + last_thread = thread; + last_context = *context; + last_debug_context = l_debug_context; +} + +static VALUE +call_at_line_unprotected(VALUE args) +{ + VALUE context; + context = *RARRAY(args)->ptr; + return rb_funcall2(context, idAtLine, RARRAY(args)->len - 1, RARRAY(args)->ptr + 1); +} + +static VALUE +call_at_line(VALUE context, debug_context_t *debug_context, VALUE file, VALUE line) +{ + VALUE args; + + last_debugged_thnum = debug_context->thnum; + save_current_position(debug_context); + + args = rb_ary_new3(3, context, file, line); + return rb_protect(call_at_line_unprotected, args, 0); +} + +static void +save_call_frame(rb_event_t event, VALUE self, char *file, int line, ID mid, debug_context_t *debug_context) +{ + VALUE binding; + debug_frame_t *debug_frame; + int frame_n; + + binding = self && RTEST(keep_frame_binding)? create_binding(self) : Qnil; + + frame_n = debug_context->stack_size++; + if(frame_n >= debug_context->stack_len) + { + debug_context->stack_len += STACK_SIZE_INCREMENT; + debug_context->frames = REALLOC_N(debug_context->frames, debug_frame_t, debug_context->stack_len); + } + debug_frame = &debug_context->frames[frame_n]; + debug_frame->argc = ruby_frame->argc; + debug_frame->file = file; + debug_frame->line = line; + debug_frame->binding = binding; + debug_frame->id = mid; + debug_frame->orig_id = mid; + debug_frame->dead = 0; + debug_frame->self = self; + debug_frame->arg_ary = Qnil; + debug_frame->info.runtime.frame = ruby_frame; + debug_frame->info.runtime.scope = ruby_scope; + debug_frame->info.runtime.dyna_vars = event == RUBY_EVENT_LINE ? ruby_dyna_vars : NULL; + if (RTEST(track_frame_args)) + copy_scalar_args(debug_frame); +} + + +#if defined DOSISH +#define isdirsep(x) ((x) == '/' || (x) == '\\') +#else +#define isdirsep(x) ((x) == '/') +#endif + +int +filename_cmp(VALUE source, char *file) +{ + char *source_ptr, *file_ptr; + int s_len, f_len, min_len; + int s,f; + int dirsep_flag = 0; + + s_len = RSTRING(source)->len; + f_len = strlen(file); + min_len = min(s_len, f_len); + + source_ptr = RSTRING(source)->ptr; + file_ptr = file; + + for( s = s_len - 1, f = f_len - 1; s >= s_len - min_len && f >= f_len - min_len; s--, f-- ) + { + if((source_ptr[s] == '.' || file_ptr[f] == '.') && dirsep_flag) + return 1; + if(isdirsep(source_ptr[s]) && isdirsep(file_ptr[f])) + dirsep_flag = 1; + else if(source_ptr[s] != file_ptr[f]) + return 0; + } + return 1; +} + +/* + * This is a NASTY HACK. For some reasons rb_f_binding is declared + * static in eval.c. So we create a cons up call to binding in C. + */ +static VALUE +create_binding(VALUE self) +{ + typedef VALUE (*bind_func_t)(VALUE); + static bind_func_t f_binding = NULL; + + if(f_binding == NULL) + { + f_binding = (bind_func_t)ruby_method_ptr(rb_mKernel, rb_intern("binding")); + } + return f_binding(self); +} + +inline static debug_frame_t * +get_top_frame(debug_context_t *debug_context) +{ + if(debug_context->stack_size == 0) + return NULL; + else + return &(debug_context->frames[debug_context->stack_size-1]); +} + +inline static void +save_top_binding(debug_context_t *debug_context, VALUE binding) +{ + debug_frame_t *debug_frame; + debug_frame = get_top_frame(debug_context); + if(debug_frame) + debug_frame->binding = binding; +} + +inline static void +set_frame_source(rb_event_t event, debug_context_t *debug_context, VALUE self, char *file, int line, ID mid) +{ + debug_frame_t *top_frame; + top_frame = get_top_frame(debug_context); + if(top_frame) + { + top_frame->self = self; + top_frame->file = file; + top_frame->line = line; + top_frame->id = mid; + top_frame->info.runtime.dyna_vars = event == RUBY_EVENT_C_CALL ? NULL : ruby_dyna_vars; + } +} + +inline static void +reset_frame_mid(debug_context_t *debug_context) +{ + debug_frame_t *top_frame; + top_frame = get_top_frame(debug_context); + if(top_frame) + { + top_frame->id = 0; + } +} + +static void +save_current_position(debug_context_t *debug_context) +{ + debug_frame_t *debug_frame; + + debug_frame = get_top_frame(debug_context); + if(!debug_frame) return; + debug_context->last_file = debug_frame->file; + debug_context->last_line = debug_frame->line; + CTX_FL_UNSET(debug_context, CTX_FL_ENABLE_BKPT); + CTX_FL_UNSET(debug_context, CTX_FL_STEPPED); + CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE); +} + +inline static char * +get_event_name(rb_event_t event) +{ + switch (event) { + case RUBY_EVENT_LINE: + return "line"; + case RUBY_EVENT_CLASS: + return "class"; + case RUBY_EVENT_END: + return "end"; + case RUBY_EVENT_CALL: + return "call"; + case RUBY_EVENT_RETURN: + return "return"; + case RUBY_EVENT_C_CALL: + return "c-call"; + case RUBY_EVENT_C_RETURN: + return "c-return"; + case RUBY_EVENT_RAISE: + return "raise"; + default: + return "unknown"; + } +} + +inline static int +c_call_new_frame_p(VALUE klass, ID mid) +{ + klass = real_class(klass); + if(rb_block_given_p()) return 1; + if(klass == rb_cProc || klass == rb_mKernel || klass == rb_cModule) return 1; + return 0; +} + +static void +debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass) +{ + VALUE thread, context; + VALUE breakpoint = Qnil, binding = Qnil; + debug_context_t *debug_context; + char *file = NULL; + int line = 0, moved = 0; + + hook_count++; + + if (mid == ID_ALLOCATOR) return; + + thread = rb_thread_current(); + thread_context_lookup(thread, &context, &debug_context); + + /* return if thread is marked as 'ignored'. + debugger's threads are marked this way + */ + if(CTX_FL_TEST(debug_context, CTX_FL_IGNORE)) return; + + while(1) + { + /* halt execution of the current thread if the debugger + is activated in another + */ + while(locker != Qnil && locker != thread) + { + add_to_locked(thread); + rb_thread_stop(); + } + + /* stop the current thread if it's marked as suspended */ + if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND) && locker != thread) + { + CTX_FL_SET(debug_context, CTX_FL_WAS_RUNNING); + rb_thread_stop(); + } + else break; + } + + /* return if the current thread is the locker */ + if(locker != Qnil) return; + + /* only the current thread can proceed */ + locker = thread; + + /* ignore a skipped section of code */ + if(CTX_FL_TEST(debug_context, CTX_FL_SKIPPED)) goto cleanup; + + if(node) + { + file = node->nd_file; + line = nd_line(node); + + if(debug == Qtrue) + fprintf(stderr, "%s:%d [%s] %s\n", file, line, get_event_name(event), rb_id2name(mid)); + + /* There can be many event calls per line, but we only want + *one* breakpoint per line. */ + if(debug_context->last_line != line || debug_context->last_file == NULL || + strcmp(debug_context->last_file, file) != 0) + { + CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT); + moved = 1; + } + else if(event == RUBY_EVENT_LINE) + { + /* There are two line-event trace hook calls per IF node - one + before the expression eval an done afterwards. + */ + /* FIXME: the static variable can't be safely used here, since this method + is re-entrant by multiple threads. If we want to provide this kind of functionality + if_eval_event variable must be moved to debug_context structure. + */ + /* + static int if_eval_event = 0; + if_eval_event = (NODE_IF == nd_type(node)) ? !if_eval_event : 0; + if (!if_eval_event) + { + CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT); + } + */ + } + } + else if(event != RUBY_EVENT_RETURN && event != RUBY_EVENT_C_RETURN) + { + if(debug == Qtrue) + fprintf(stderr, "nodeless [%s] %s\n", get_event_name(event), rb_id2name(mid)); + goto cleanup; + } + else + { + if(debug == Qtrue) + fprintf(stderr, "nodeless [%s] %s\n", get_event_name(event), rb_id2name(mid)); + } + + if(event != RUBY_EVENT_LINE) + CTX_FL_SET(debug_context, CTX_FL_STEPPED); + + switch(event) + { + case RUBY_EVENT_LINE: + { + + if(debug_context->stack_size == 0) + save_call_frame(event, self, file, line, mid, debug_context); + else + set_frame_source(event, debug_context, self, file, line, mid); + + if(RTEST(tracing) || CTX_FL_TEST(debug_context, CTX_FL_TRACING)) + rb_funcall(context, idAtTracing, 2, rb_str_new2(file), INT2FIX(line)); + + if(debug_context->dest_frame == -1 || + debug_context->stack_size == debug_context->dest_frame) + { + if(moved || !CTX_FL_TEST(debug_context, CTX_FL_FORCE_MOVE)) + debug_context->stop_next--; + if(debug_context->stop_next < 0) + debug_context->stop_next = -1; + if(moved || (CTX_FL_TEST(debug_context, CTX_FL_STEPPED) && + !CTX_FL_TEST(debug_context, CTX_FL_FORCE_MOVE))) + { + debug_context->stop_line--; + CTX_FL_UNSET(debug_context, CTX_FL_STEPPED); + } + } + else if(debug_context->stack_size < debug_context->dest_frame) + { + debug_context->stop_next = 0; + } + + if(debug_context->stop_next == 0 || debug_context->stop_line == 0 || + (breakpoint = check_breakpoints_by_pos(debug_context, file, line)) != Qnil) + { + binding = self? create_binding(self) : Qnil; + save_top_binding(debug_context, binding); + + debug_context->stop_reason = CTX_STOP_STEP; + + /* check breakpoint expression */ + if(breakpoint != Qnil) + { + if(!check_breakpoint_expression(breakpoint, binding)) + break; + if(!check_breakpoint_hit_condition(breakpoint)) + break; + if(breakpoint != debug_context->breakpoint) + { + debug_context->stop_reason = CTX_STOP_BREAKPOINT; + rb_funcall(context, idAtBreakpoint, 1, breakpoint); + } + else + debug_context->breakpoint = Qnil; + } + + reset_stepping_stop_points(debug_context); + call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line)); + } + break; + } + case RUBY_EVENT_CALL: + { + save_call_frame(event, self, file, line, mid, debug_context); + breakpoint = check_breakpoints_by_method(debug_context, klass, mid); + if(breakpoint != Qnil) + { + debug_frame_t *debug_frame; + debug_frame = get_top_frame(debug_context); + if(debug_frame) + binding = debug_frame->binding; + if(NIL_P(binding) && self) + binding = create_binding(self); + save_top_binding(debug_context, binding); + + if(!check_breakpoint_expression(breakpoint, binding)) + break; + if(!check_breakpoint_hit_condition(breakpoint)) + break; + if(breakpoint != debug_context->breakpoint) + { + debug_context->stop_reason = CTX_STOP_BREAKPOINT; + rb_funcall(context, idAtBreakpoint, 1, breakpoint); + } + else + debug_context->breakpoint = Qnil; + call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line)); + } + break; + } + case RUBY_EVENT_C_CALL: + { + if(c_call_new_frame_p(klass, mid)) + save_call_frame(event, self, file, line, mid, debug_context); + else + set_frame_source(event, debug_context, self, file, line, mid); + break; + } + case RUBY_EVENT_C_RETURN: + { + /* note if a block is given we fall through! */ + if(!node || !c_call_new_frame_p(klass, mid)) + break; + } + case RUBY_EVENT_RETURN: + case RUBY_EVENT_END: + { + if(debug_context->stack_size == debug_context->stop_frame) + { + debug_context->stop_next = 1; + debug_context->stop_frame = 0; + /* NOTE: can't use call_at_line function here to trigger a debugger event. + this can lead to segfault. We should only unroll the stack on this event. + */ + } + while(debug_context->stack_size > 0) + { + debug_context->stack_size--; + if(debug_context->frames[debug_context->stack_size].orig_id == mid) + break; + } + CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT); + break; + } + case RUBY_EVENT_CLASS: + { + reset_frame_mid(debug_context); + save_call_frame(event, self, file, line, mid, debug_context); + break; + } + case RUBY_EVENT_RAISE: + { + VALUE ancestors; + VALUE expn_class, aclass; + int i; + + set_frame_source(event, debug_context, self, file, line, mid); + + if(post_mortem == Qtrue && self) + { + binding = create_binding(self); + rb_ivar_set(ruby_errinfo, rb_intern("@__debug_file"), rb_str_new2(file)); + rb_ivar_set(ruby_errinfo, rb_intern("@__debug_line"), INT2FIX(line)); + rb_ivar_set(ruby_errinfo, rb_intern("@__debug_binding"), binding); + rb_ivar_set(ruby_errinfo, rb_intern("@__debug_context"), debug_context_dup(debug_context)); + } + + expn_class = rb_obj_class(ruby_errinfo); + + /* This code goes back to the earliest days of ruby-debug. It + tends to disallow catching an exception via the + "catchpoint" command. To address this one possiblilty is to + move this after testing for catchponts. Kent however thinks + there may be a misfeature in Ruby's eval.c: the problem was + in the fact that Ruby doesn't reset exception flag on the + current thread before it calls a notification handler. + + See also the #ifdef'd code below as well. + */ +#ifdef NORMAL_CODE + if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) ) + { + debug_stop(mDebugger); + break; + } +#endif + + if (rdebug_catchpoints == Qnil || + RHASH(rdebug_catchpoints)->tbl->num_entries == 0) + break; + + ancestors = rb_mod_ancestors(expn_class); + for(i = 0; i < RARRAY(ancestors)->len; i++) + { + VALUE mod_name; + VALUE hit_count; + + aclass = rb_ary_entry(ancestors, i); + mod_name = rb_mod_name(aclass); + hit_count = rb_hash_aref(rdebug_catchpoints, mod_name); + if(hit_count != Qnil) + { + hit_count = INT2FIX(FIX2INT(rb_hash_aref(rdebug_catchpoints, + mod_name)+1)); + rb_hash_aset(rdebug_catchpoints, mod_name, hit_count); + debug_context->stop_reason = CTX_STOP_CATCHPOINT; + rb_funcall(context, idAtCatchpoint, 1, ruby_errinfo); + if(self && binding == Qnil) + binding = create_binding(self); + save_top_binding(debug_context, binding); + call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line)); + break; + } + } + + /* If we stop the debugger, we may not be able to trace into + code that has an exception handler wrapped around it. So + the alternative is to force the user to do his own + Debugger.stop. */ +#ifdef NORMAL_CODE_MOVING_AFTER_ + if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) ) + { + debug_stop(mDebugger); + break; + } +#endif + + break; + } + } + + cleanup: + + debug_context->stop_reason = CTX_STOP_NONE; + + /* check that all contexts point to alive threads */ + if(hook_count - last_check > 3000) + { + check_thread_contexts(); + last_check = hook_count; + } + + /* release a lock */ + locker = Qnil; + /* let the next thread to run */ + thread = remove_from_locked(); + if(thread != Qnil) + rb_thread_run(thread); +} + +static VALUE +debug_stop_i(VALUE self) +{ + if(IS_STARTED) + debug_stop(self); + return Qnil; +} + +/* + * call-seq: + * Debugger.start_ -> bool + * Debugger.start_ { ... } -> bool + * + * This method is internal and activates the debugger. Use + * Debugger.start (from lib/ruby-debug-base.rb) instead. + * + * The return value is the value of !Debugger.started? before + * issuing the +start+; That is, +true+ is returned, unless debugger + * was previously started. + + * If a block is given, it starts debugger and yields to block. When + * the block is finished executing it stops the debugger with + * Debugger.stop method. Inside the block you will probably want to + * have a call to Debugger.debugger. For example: + * Debugger.start{debugger; foo} # Stop inside of foo + * + * Also, ruby-debug only allows + * one invocation of debugger at a time; nested Debugger.start's + * have no effect and you can't use this inside the debugger itself. + * + * Note that if you want to completely remove the debugger hook, + * you must call Debugger.stop as many times as you called + * Debugger.start method. + */ +static VALUE +debug_start(VALUE self) +{ + VALUE result; + start_count++; + + if(IS_STARTED) + result = Qfalse; + else + { + locker = Qnil; + rdebug_breakpoints = rb_ary_new(); + rdebug_catchpoints = rb_hash_new(); + rdebug_threads_tbl = threads_table_create(); + + rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL); + result = Qtrue; + } + + if(rb_block_given_p()) + rb_ensure(rb_yield, self, debug_stop_i, self); + + return result; +} + +/* + * call-seq: + * Debugger.stop -> bool + * + * This method disables the debugger. It returns +true+ if the debugger is disabled, + * otherwise it returns +false+. + * + * Note that if you want to complete remove the debugger hook, + * you must call Debugger.stop as many times as you called + * Debugger.start method. + */ +static VALUE +debug_stop(VALUE self) +{ + debug_check_started(); + + start_count--; + if(start_count) + return Qfalse; + + rb_remove_event_hook(debug_event_hook); + + locker = Qnil; + rdebug_breakpoints = Qnil; + rdebug_threads_tbl = Qnil; + + return Qtrue; +} + +static int +find_last_context_func(VALUE key, VALUE value, VALUE *result) +{ + debug_context_t *debug_context; + Data_Get_Struct(value, debug_context_t, debug_context); + if(debug_context->thnum == last_debugged_thnum) + { + *result = value; + return ST_STOP; + } + return ST_CONTINUE; +} + +/* + * call-seq: + * Debugger.last_interrupted -> context + * + * Returns last debugged context. + */ +static VALUE +debug_last_interrupted(VALUE self) +{ + VALUE result = Qnil; + threads_table_t *threads_table; + + debug_check_started(); + + Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table); + + st_foreach(threads_table->tbl, find_last_context_func, (st_data_t)&result); + return result; +} + +/* + * call-seq: + * Debugger.current_context -> context + * + * Returns current context. + * Note: Debugger.current_context.thread == Thread.current + */ +static VALUE +debug_current_context(VALUE self) +{ + VALUE thread, context; + + debug_check_started(); + + thread = rb_thread_current(); + thread_context_lookup(thread, &context, NULL); + + return context; +} + +/* + * call-seq: + * Debugger.thread_context(thread) -> context + * + * Returns context of the thread passed as an argument. + */ +static VALUE +debug_thread_context(VALUE self, VALUE thread) +{ + VALUE context; + + debug_check_started(); + thread_context_lookup(thread, &context, NULL); + return context; +} + +/* + * call-seq: + * Debugger.contexts -> array + * + * Returns an array of all contexts. + */ +static VALUE +debug_contexts(VALUE self) +{ + volatile VALUE list; + volatile VALUE new_list; + VALUE thread, context; + threads_table_t *threads_table; + debug_context_t *debug_context; + int i; + + debug_check_started(); + + new_list = rb_ary_new(); + list = rb_funcall(rb_cThread, idList, 0); + for(i = 0; i < RARRAY(list)->len; i++) + { + thread = rb_ary_entry(list, i); + thread_context_lookup(thread, &context, NULL); + rb_ary_push(new_list, context); + } + threads_table_clear(rdebug_threads_tbl); + Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table); + for(i = 0; i < RARRAY(new_list)->len; i++) + { + context = rb_ary_entry(new_list, i); + Data_Get_Struct(context, debug_context_t, debug_context); + st_insert(threads_table->tbl, debug_context->thread_id, context); + } + + return new_list; +} + +/* + * call-seq: + * Debugger.suspend -> Debugger + * + * Suspends all contexts. + */ +static VALUE +debug_suspend(VALUE self) +{ + VALUE current, context; + VALUE saved_crit; + VALUE context_list; + debug_context_t *debug_context; + int i; + + debug_check_started(); + + saved_crit = rb_thread_critical; + rb_thread_critical = Qtrue; + context_list = debug_contexts(self); + thread_context_lookup(rb_thread_current(), ¤t, NULL); + + for(i = 0; i < RARRAY(context_list)->len; i++) + { + context = rb_ary_entry(context_list, i); + if(current == context) + continue; + Data_Get_Struct(context, debug_context_t, debug_context); + context_suspend_0(debug_context); + } + rb_thread_critical = saved_crit; + + if(rb_thread_critical == Qfalse) + rb_thread_schedule(); + + return self; +} + +/* + * call-seq: + * Debugger.resume -> Debugger + * + * Resumes all contexts. + */ +static VALUE +debug_resume(VALUE self) +{ + VALUE current, context; + VALUE saved_crit; + VALUE context_list; + debug_context_t *debug_context; + int i; + + debug_check_started(); + + saved_crit = rb_thread_critical; + rb_thread_critical = Qtrue; + context_list = debug_contexts(self); + + thread_context_lookup(rb_thread_current(), ¤t, NULL); + for(i = 0; i < RARRAY(context_list)->len; i++) + { + context = rb_ary_entry(context_list, i); + if(current == context) + continue; + Data_Get_Struct(context, debug_context_t, debug_context); + context_resume_0(debug_context); + } + rb_thread_critical = saved_crit; + + rb_thread_schedule(); + + return self; +} + +/* + * call-seq: + * Debugger.tracing -> bool + * + * Returns +true+ if the global tracing is activated. + */ +static VALUE +debug_tracing(VALUE self) +{ + return tracing; +} + +/* + * call-seq: + * Debugger.tracing = bool + * + * Sets the global tracing flag. + */ +static VALUE +debug_set_tracing(VALUE self, VALUE value) +{ + tracing = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* + * call-seq: + * Debugger.post_mortem? -> bool + * + * Returns +true+ if post-moterm debugging is enabled. + */ +static VALUE +debug_post_mortem(VALUE self) +{ + return post_mortem; +} + +/* + * call-seq: + * Debugger.post_mortem = bool + * + * Sets post-moterm flag. + * FOR INTERNAL USE ONLY. + */ +static VALUE +debug_set_post_mortem(VALUE self, VALUE value) +{ + debug_check_started(); + + post_mortem = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* + * call-seq: + * Debugger.track_fame_args? -> bool + * + * Returns +true+ if the debugger track frame argument values on calls. + */ +static VALUE +debug_track_frame_args(VALUE self) +{ + return track_frame_args; +} + +/* + * call-seq: + * Debugger.track_frame_args = bool + * + * Setting to +true+ will make the debugger save argument info on calls. + */ +static VALUE +debug_set_track_frame_args(VALUE self, VALUE value) +{ + track_frame_args = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* + * call-seq: + * Debugger.keep_frame_binding? -> bool + * + * Returns +true+ if the debugger will collect frame bindings. + */ +static VALUE +debug_keep_frame_binding(VALUE self) +{ + return keep_frame_binding; +} + +/* + * call-seq: + * Debugger.keep_frame_binding = bool + * + * Setting to +true+ will make the debugger create frame bindings. + */ +static VALUE +debug_set_keep_frame_binding(VALUE self, VALUE value) +{ + keep_frame_binding = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* :nodoc: */ +static VALUE +debug_debug(VALUE self) +{ + return debug; +} + +/* :nodoc: */ +static VALUE +debug_set_debug(VALUE self, VALUE value) +{ + debug = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* :nodoc: */ +static VALUE +debug_thread_inherited(VALUE klass) +{ + rb_raise(rb_eRuntimeError, "Can't inherite Debugger::DebugThread class"); +} + +/* + * call-seq: + * Debugger.debug_load(file, stop = false, increment_start = false) -> nil + * + * Same as Kernel#load but resets current context's frames. + * +stop+ parameter forces the debugger to stop at the first line of code in the +file+ + * +increment_start+ determines if start_count should be incremented. When + * control threads are used, they have to be set up before loading the + * debugger; so here +increment_start+ will be false. + * FOR INTERNAL USE ONLY. + */ +static VALUE +debug_debug_load(int argc, VALUE *argv, VALUE self) +{ + VALUE file, stop, context, increment_start; + debug_context_t *debug_context; + int state = 0; + + if(rb_scan_args(argc, argv, "12", &file, &stop, &increment_start) == 1) + { + stop = Qfalse; + increment_start = Qtrue; + } + + debug_start(self); + if (Qfalse == increment_start) start_count--; + + context = debug_current_context(self); + Data_Get_Struct(context, debug_context_t, debug_context); + debug_context->stack_size = 0; + if(RTEST(stop)) + debug_context->stop_next = 1; + /* Initializing $0 to the script's path */ + ruby_script(RSTRING(file)->ptr); + rb_load_protect(file, 0, &state); + if (0 != state) { + VALUE errinfo = ruby_errinfo; + debug_suspend(self); + reset_stepping_stop_points(debug_context); + ruby_errinfo = Qnil; + return errinfo; + } + + /* We should run all at_exit handler's in order to provide, + * for instance, a chance to run all defined test cases */ + rb_exec_end_proc(); + + /* We could have issued a Debugger.stop inside the debug + session. */ + if (start_count > 0) { + debug_stop(self); + } + + return Qnil; +} + +static VALUE +set_current_skipped_status(VALUE status) +{ + VALUE context; + debug_context_t *debug_context; + + context = debug_current_context(Qnil); + Data_Get_Struct(context, debug_context_t, debug_context); + if(status) + CTX_FL_SET(debug_context, CTX_FL_SKIPPED); + else + CTX_FL_UNSET(debug_context, CTX_FL_SKIPPED); + return Qnil; +} + +/* + * call-seq: + * Debugger.skip { block } -> obj or nil + * + * The code inside of the block is escaped from the debugger. + */ +static VALUE +debug_skip(VALUE self) +{ + if (!rb_block_given_p()) { + rb_raise(rb_eArgError, "called without a block"); + } + if(!IS_STARTED) + return rb_yield(Qnil); + set_current_skipped_status(Qtrue); + return rb_ensure(rb_yield, Qnil, set_current_skipped_status, Qfalse); +} + +static VALUE +debug_at_exit_c(VALUE proc) +{ + return rb_funcall(proc, rb_intern("call"), 0); +} + +static void +debug_at_exit_i(VALUE proc) +{ + if(!IS_STARTED) + { + debug_at_exit_c(proc); + } + else + { + set_current_skipped_status(Qtrue); + rb_ensure(debug_at_exit_c, proc, set_current_skipped_status, Qfalse); + } +} + +/* + * call-seq: + * Debugger.debug_at_exit { block } -> proc + * + * Register at_exit hook which is escaped from the debugger. + * FOR INTERNAL USE ONLY. + */ +static VALUE +debug_at_exit(VALUE self) +{ + VALUE proc; + if (!rb_block_given_p()) + rb_raise(rb_eArgError, "called without a block"); + proc = rb_block_proc(); + rb_set_end_proc(debug_at_exit_i, proc); + return proc; +} + +/* + * call-seq: + * context.step(steps, force = false) + * + * Stops the current context after a number of +steps+ are made. + * +force+ parameter (if true) ensures that the cursor moves from the current line. + */ +static VALUE +context_stop_next(int argc, VALUE *argv, VALUE self) +{ + VALUE steps, force; + debug_context_t *debug_context; + + debug_check_started(); + + rb_scan_args(argc, argv, "11", &steps, &force); + if(FIX2INT(steps) < 0) + rb_raise(rb_eRuntimeError, "Steps argument can't be negative."); + + Data_Get_Struct(self, debug_context_t, debug_context); + debug_context->stop_next = FIX2INT(steps); + if(RTEST(force)) + CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE); + else + CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE); + + return steps; +} + +/* + * call-seq: + * context.step_over(steps, frame = nil, force = false) + * + * Steps over a +steps+ number of times. + * Make step over operation on +frame+, by default the current frame. + * +force+ parameter (if true) ensures that the cursor moves from the current line. + */ +static VALUE +context_step_over(int argc, VALUE *argv, VALUE self) +{ + VALUE lines, frame, force; + debug_context_t *debug_context; + + debug_check_started(); + Data_Get_Struct(self, debug_context_t, debug_context); + if(debug_context->stack_size == 0) + rb_raise(rb_eRuntimeError, "No frames collected."); + + rb_scan_args(argc, argv, "12", &lines, &frame, &force); + debug_context->stop_line = FIX2INT(lines); + CTX_FL_UNSET(debug_context, CTX_FL_STEPPED); + if(frame == Qnil) + { + debug_context->dest_frame = debug_context->stack_size; + } + else + { + if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size) + rb_raise(rb_eRuntimeError, "Destination frame is out of range."); + debug_context->dest_frame = debug_context->stack_size - FIX2INT(frame); + } + if(RTEST(force)) + CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE); + else + CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE); + + return Qnil; +} + +/* + * call-seq: + * context.stop_frame(frame) + * + * Stops when a frame with number +frame+ is activated. Implements +finish+ and +next+ commands. + */ +static VALUE +context_stop_frame(VALUE self, VALUE frame) +{ + debug_context_t *debug_context; + + debug_check_started(); + Data_Get_Struct(self, debug_context_t, debug_context); + if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size) + rb_raise(rb_eRuntimeError, "Stop frame is out of range."); + debug_context->stop_frame = debug_context->stack_size - FIX2INT(frame); + + return frame; +} + +inline static int +check_frame_number(debug_context_t *debug_context, VALUE frame) +{ + int frame_n; + + frame_n = FIX2INT(frame); + if(frame_n < 0 || frame_n >= debug_context->stack_size) + rb_raise(rb_eArgError, "Invalid frame number %d, stack (0...%d)", + frame_n, debug_context->stack_size); + return frame_n; +} + +static int +optional_frame_position(int argc, VALUE *argv) { + unsigned int i_scanned; + VALUE level; + + if ((argc > 1) || (argc < 0)) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc); + i_scanned = rb_scan_args(argc, argv, "01", &level); + if (0 == i_scanned) { + level = INT2FIX(0); + } + return level; +} + +/* + * call-seq: + * context.frame_args_info(frame_position=0) -> list + if track_frame_args or nil otherwise + * + * Returns info saved about call arguments (if any saved). + */ +static VALUE +context_frame_args_info(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + return RTEST(track_frame_args) ? GET_FRAME->arg_ary : Qnil; +} + +/* + * call-seq: + * context.frame_binding(frame_position=0) -> binding + * + * Returns frame's binding. + */ +static VALUE +context_frame_binding(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + return GET_FRAME->binding; +} + +/* + * call-seq: + * context.frame_method(frame_position=0) -> sym + * + * Returns the sym of the called method. + */ +static VALUE +context_frame_id(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + ID id; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + id = GET_FRAME->id; + return id ? ID2SYM(id): Qnil; +} + +/* + * call-seq: + * context.frame_line(frame_position) -> int + * + * Returns the line number in the file. + */ +static VALUE +context_frame_line(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + return INT2FIX(GET_FRAME->line); +} + +/* + * call-seq: + * context.frame_file(frame_position) -> string + * + * Returns the name of the file. + */ +static VALUE +context_frame_file(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + return rb_str_new2(GET_FRAME->file); +} + +static int +arg_value_is_small(VALUE val) +{ + switch (TYPE(val)) { + case T_FIXNUM: case T_FLOAT: case T_CLASS: + case T_NIL: case T_MODULE: case T_FILE: + case T_TRUE: case T_FALSE: case T_UNDEF: + return 1; + default: + return SYMBOL_P(val); + } +} + +/* + * Save scalar arguments or a class name. + */ +static void +copy_scalar_args(debug_frame_t *debug_frame) +{ + unsigned int i; + ID *tbl = ruby_scope->local_tbl;; + if (tbl && ruby_scope->local_vars) + { + int n = *tbl++; + if (debug_frame->argc+2 < n) n = debug_frame->argc+2; + debug_frame->arg_ary = rb_ary_new2(n); + for (i=2; iarg_ary, val); + else + rb_ary_push(debug_frame->arg_ary, + rb_str_new2(rb_obj_classname(val))); + } + } + } +} + + +/* + * call-seq: + * context.copy_args(frame) -> list of args + * + * Returns a array of argument names. + */ +static VALUE +context_copy_args(debug_frame_t *debug_frame) +{ + ID *tbl; + int n, i; + struct SCOPE *scope; + VALUE list = rb_ary_new2(0); /* [] */ + + scope = debug_frame->info.runtime.scope; + tbl = scope->local_tbl; + + if (tbl && scope->local_vars) + { + n = *tbl++; + if (debug_frame->argc+2 < n) n = debug_frame->argc+2; + list = rb_ary_new2(n); + /* skip first 2 ($_ and $~) */ + for (i=2; iinfo.runtime.scope; + tbl = scope->local_tbl; + + if (tbl && scope->local_vars) + { + n = *tbl++; + for (i=2; ilocal_vars[i]); + } + } + + vars = debug_frame->info.runtime.dyna_vars; + while (vars) + { + if (vars->id && rb_is_local_id(vars->id)) + { /* skip $_, $~ and flip states */ + rb_hash_aset(hash, rb_str_new2(rb_id2name(vars->id)), vars->val); + } + vars = vars->next; + } + return hash; +} + +/* + * call-seq: + * context.frame_locals(frame) -> hash + * + * Returns frame's local variables. + */ +static VALUE +context_frame_locals(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + debug_frame_t *debug_frame; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + debug_frame = GET_FRAME; + if(debug_frame->dead) + return debug_frame->info.copy.locals; + else + return context_copy_locals(debug_frame); +} + +/* + * call-seq: + * context.frame_args(frame_position=0) -> list + * + * Returns frame's argument parameters + */ +static VALUE +context_frame_args(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + debug_frame_t *debug_frame; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + debug_frame = GET_FRAME; + if(debug_frame->dead) + return debug_frame->info.copy.args; + else + return context_copy_args(debug_frame); +} + +/* + * call-seq: + * context.frame_self(frame_postion=0) -> obj + * + * Returns self object of the frame. + */ +static VALUE +context_frame_self(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + debug_frame_t *debug_frame; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + debug_frame = GET_FRAME; + return debug_frame->self; +} + +/* + * call-seq: + * context.frame_class(frame_position) -> obj + * + * Returns the real class of the frame. + * It could be different than context.frame_self(frame).class + */ +static VALUE +context_frame_class(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + debug_frame_t *debug_frame; + VALUE klass; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + debug_frame = GET_FRAME; + + if(CTX_FL_TEST(debug_context, CTX_FL_DEAD)) + return Qnil; + +#if RUBY_VERSION_CODE >= 190 + klass = debug_frame->info.runtime.frame->this_class; +#else + klass = debug_frame->info.runtime.frame->last_class; +#endif + + klass = real_class(klass); + if(TYPE(klass) == T_CLASS || TYPE(klass) == T_MODULE) + return klass; + return Qnil; +} + + +/* + * call-seq: + * context.stack_size-> int + * + * Returns the size of the context stack. + */ +static VALUE +context_stack_size(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + Data_Get_Struct(self, debug_context_t, debug_context); + + return INT2FIX(debug_context->stack_size); +} + +/* + * call-seq: + * context.thread -> thread + * + * Returns a thread this context is associated with. + */ +static VALUE +context_thread(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + Data_Get_Struct(self, debug_context_t, debug_context); + return context_thread_0(debug_context); +} + +/* + * call-seq: + * context.thnum -> int + * + * Returns the context's number. + */ +static VALUE +context_thnum(VALUE self) +{ + debug_context_t *debug_context; + + Data_Get_Struct(self, debug_context_t, debug_context); + return INT2FIX(debug_context->thnum); +} + +static void +context_suspend_0(debug_context_t *debug_context) +{ + VALUE status; + + status = rb_funcall(context_thread_0(debug_context), rb_intern("status"), 0); + if(rb_str_cmp(status, rb_str_new2("run")) == 0) + CTX_FL_SET(debug_context, CTX_FL_WAS_RUNNING); + else if(rb_str_cmp(status, rb_str_new2("sleep")) == 0) + CTX_FL_UNSET(debug_context, CTX_FL_WAS_RUNNING); + else + return; + CTX_FL_SET(debug_context, CTX_FL_SUSPEND); +} + +static void +context_resume_0(debug_context_t *debug_context) +{ + if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND)) + return; + CTX_FL_UNSET(debug_context, CTX_FL_SUSPEND); + if(CTX_FL_TEST(debug_context, CTX_FL_WAS_RUNNING)) + rb_thread_wakeup(context_thread_0(debug_context)); +} + +/* + * call-seq: + * context.suspend -> nil + * + * Suspends the thread when it is running. + */ +static VALUE +context_suspend(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND)) + rb_raise(rb_eRuntimeError, "Already suspended."); + context_suspend_0(debug_context); + return Qnil; +} + +/* + * call-seq: + * context.suspended? -> bool + * + * Returns +true+ if the thread is suspended by debugger. + */ +static VALUE +context_is_suspended(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return CTX_FL_TEST(debug_context, CTX_FL_SUSPEND) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * context.resume -> nil + * + * Resumes the thread from the suspended mode. + */ +static VALUE +context_resume(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND)) + rb_raise(rb_eRuntimeError, "Thread is not suspended."); + context_resume_0(debug_context); + return Qnil; +} + +/* + * call-seq: + * context.tracing -> bool + * + * Returns the tracing flag for the current context. + */ +static VALUE +context_tracing(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return CTX_FL_TEST(debug_context, CTX_FL_TRACING) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * context.tracing = bool + * + * Controls the tracing for this context. + */ +static VALUE +context_set_tracing(VALUE self, VALUE value) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + if(RTEST(value)) + CTX_FL_SET(debug_context, CTX_FL_TRACING); + else + CTX_FL_UNSET(debug_context, CTX_FL_TRACING); + return value; +} + +/* + * call-seq: + * context.ignored? -> bool + * + * Returns the ignore flag for the current context. + */ +static VALUE +context_ignored(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return CTX_FL_TEST(debug_context, CTX_FL_IGNORE) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * context.dead? -> bool + * + * Returns +true+ if context doesn't represent a live context and is created + * during post-mortem exception handling. + */ +static VALUE +context_dead(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return CTX_FL_TEST(debug_context, CTX_FL_DEAD) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * context.stop_reason -> sym + * + * Returns the reason for the stop. It maybe of the following values: + * :initial, :step, :breakpoint, :catchpoint, :post-mortem + */ +static VALUE +context_stop_reason(VALUE self) +{ + debug_context_t *debug_context; + char * sym_name; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + + switch(debug_context->stop_reason) + { + case CTX_STOP_STEP: + sym_name = "step"; + break; + case CTX_STOP_BREAKPOINT: + sym_name = "breakpoint"; + break; + case CTX_STOP_CATCHPOINT: + sym_name = "catchpoint"; + break; + case CTX_STOP_NONE: + default: + sym_name = "none"; + } + if(CTX_FL_TEST(debug_context, CTX_FL_DEAD)) + sym_name = "post-mortem"; + + return ID2SYM(rb_intern(sym_name)); +} + + +/* + * Document-class: Context + * + * == Summary + * + * Debugger keeps a single instance of this class for each Ruby thread. + */ +static void +Init_context() +{ + cContext = rb_define_class_under(mDebugger, "Context", rb_cObject); + rb_define_method(cContext, "stop_next=", context_stop_next, -1); + rb_define_method(cContext, "step", context_stop_next, -1); + rb_define_method(cContext, "step_over", context_step_over, -1); + rb_define_method(cContext, "stop_frame=", context_stop_frame, 1); + rb_define_method(cContext, "thread", context_thread, 0); + rb_define_method(cContext, "thnum", context_thnum, 0); + rb_define_method(cContext, "stop_reason", context_stop_reason, 0); + rb_define_method(cContext, "suspend", context_suspend, 0); + rb_define_method(cContext, "suspended?", context_is_suspended, 0); + rb_define_method(cContext, "resume", context_resume, 0); + rb_define_method(cContext, "tracing", context_tracing, 0); + rb_define_method(cContext, "tracing=", context_set_tracing, 1); + rb_define_method(cContext, "ignored?", context_ignored, 0); + rb_define_method(cContext, "frame_args", context_frame_args, -1); + rb_define_method(cContext, "frame_args_info", context_frame_args_info, -1); + rb_define_method(cContext, "frame_binding", context_frame_binding, -1); + rb_define_method(cContext, "frame_class", context_frame_class, -1); + rb_define_method(cContext, "frame_file", context_frame_file, -1); + rb_define_method(cContext, "frame_id", context_frame_id, -1); + rb_define_method(cContext, "frame_line", context_frame_line, -1); + rb_define_method(cContext, "frame_locals", context_frame_locals, -1); + rb_define_method(cContext, "frame_method", context_frame_id, -1); + rb_define_method(cContext, "frame_self", context_frame_self, -1); + rb_define_method(cContext, "stack_size", context_stack_size, 0); + rb_define_method(cContext, "dead?", context_dead, 0); + rb_define_method(cContext, "breakpoint", + context_breakpoint, 0); /* in breakpoint.c */ + rb_define_method(cContext, "set_breakpoint", + context_set_breakpoint, -1); /* in breakpoint.c */ +} + +/* + * call-seq: + * Debugger.breakpoints -> array + * + * Returns an array of breakpoints. + */ +static VALUE +debug_breakpoints(VALUE self) +{ + debug_check_started(); + + return rdebug_breakpoints; +} + +/* + * call-seq: + * Debugger.add_breakpoint(source, pos, condition = nil) -> breakpoint + * + * Adds a new breakpoint. + * source is a name of a file or a class. + * pos is a line number or a method name if source is a class name. + * condition is a string which is evaluated to +true+ when this breakpoint + * is activated. + */ +static VALUE +debug_add_breakpoint(int argc, VALUE *argv, VALUE self) +{ + VALUE result; + + debug_check_started(); + + result = create_breakpoint_from_args(argc, argv, ++bkp_count); + rb_ary_push(rdebug_breakpoints, result); + return result; +} + +/* + * Document-class: Debugger + * + * == Summary + * + * This is a singleton class allows controlling the debugger. Use it to start/stop debugger, + * set/remove breakpoints, etc. + */ +#if defined(_WIN32) +__declspec(dllexport) +#endif +void +Init_ruby_debug() +{ + mDebugger = rb_define_module("Debugger"); + rb_define_const(mDebugger, "VERSION", rb_str_new2(DEBUG_VERSION)); + rb_define_module_function(mDebugger, "start_", debug_start, 0); + rb_define_module_function(mDebugger, "stop", debug_stop, 0); + rb_define_module_function(mDebugger, "started?", debug_is_started, 0); + rb_define_module_function(mDebugger, "breakpoints", debug_breakpoints, 0); + rb_define_module_function(mDebugger, "add_breakpoint", debug_add_breakpoint, -1); + rb_define_module_function(mDebugger, "remove_breakpoint", + rdebug_remove_breakpoint, + 1); /* in breakpoint.c */ + rb_define_module_function(mDebugger, "add_catchpoint", + rdebug_add_catchpoint, 1); /* in breakpoint.c */ + rb_define_module_function(mDebugger, "catchpoints", + debug_catchpoints, 0); /* in breakpoint.c */ + rb_define_module_function(mDebugger, "last_context", debug_last_interrupted, 0); + rb_define_module_function(mDebugger, "contexts", debug_contexts, 0); + rb_define_module_function(mDebugger, "current_context", debug_current_context, 0); + rb_define_module_function(mDebugger, "thread_context", debug_thread_context, 1); + rb_define_module_function(mDebugger, "suspend", debug_suspend, 0); + rb_define_module_function(mDebugger, "resume", debug_resume, 0); + rb_define_module_function(mDebugger, "tracing", debug_tracing, 0); + rb_define_module_function(mDebugger, "tracing=", debug_set_tracing, 1); + rb_define_module_function(mDebugger, "debug_load", debug_debug_load, -1); + rb_define_module_function(mDebugger, "skip", debug_skip, 0); + rb_define_module_function(mDebugger, "debug_at_exit", debug_at_exit, 0); + rb_define_module_function(mDebugger, "post_mortem?", debug_post_mortem, 0); + rb_define_module_function(mDebugger, "post_mortem=", debug_set_post_mortem, 1); + rb_define_module_function(mDebugger, "keep_frame_binding?", + debug_keep_frame_binding, 0); + rb_define_module_function(mDebugger, "keep_frame_binding=", + debug_set_keep_frame_binding, 1); + rb_define_module_function(mDebugger, "track_frame_args?", + debug_track_frame_args, 0); + rb_define_module_function(mDebugger, "track_frame_args=", + debug_set_track_frame_args, 1); + rb_define_module_function(mDebugger, "debug", debug_debug, 0); + rb_define_module_function(mDebugger, "debug=", debug_set_debug, 1); + + cThreadsTable = rb_define_class_under(mDebugger, "ThreadsTable", rb_cObject); + + cDebugThread = rb_define_class_under(mDebugger, "DebugThread", rb_cThread); + rb_define_singleton_method(cDebugThread, "inherited", + debug_thread_inherited, 1); + + Init_context(); + Init_breakpoint(); + + idAtBreakpoint = rb_intern("at_breakpoint"); + idAtCatchpoint = rb_intern("at_catchpoint"); + idAtLine = rb_intern("at_line"); + idAtReturn = rb_intern("at_return"); + idAtTracing = rb_intern("at_tracing"); + idList = rb_intern("list"); + + rb_mObjectSpace = rb_const_get(rb_mKernel, rb_intern("ObjectSpace")); + + rb_global_variable(&last_context); + rb_global_variable(&last_thread); + rb_global_variable(&locker); + rb_global_variable(&rdebug_breakpoints); + rb_global_variable(&rdebug_catchpoints); + rb_global_variable(&rdebug_threads_tbl); +} diff --git a/ext/.svn/text-base/ruby_debug.h.svn-base b/ext/.svn/text-base/ruby_debug.h.svn-base new file mode 100644 index 0000000..04a8ae2 --- /dev/null +++ b/ext/.svn/text-base/ruby_debug.h.svn-base @@ -0,0 +1,123 @@ +#include +/* Context info */ +enum ctx_stop_reason {CTX_STOP_NONE, CTX_STOP_STEP, CTX_STOP_BREAKPOINT, + CTX_STOP_CATCHPOINT}; + +/* Context flags */ +#define CTX_FL_SUSPEND (1<<1) +#define CTX_FL_TRACING (1<<2) +#define CTX_FL_SKIPPED (1<<3) +#define CTX_FL_IGNORE (1<<4) +#define CTX_FL_DEAD (1<<5) +#define CTX_FL_WAS_RUNNING (1<<6) +#define CTX_FL_ENABLE_BKPT (1<<7) +#define CTX_FL_STEPPED (1<<8) +#define CTX_FL_FORCE_MOVE (1<<9) + +#define CTX_FL_TEST(c,f) ((c)->flags & (f)) +#define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0) +#define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0) + +typedef struct { + int argc; /* Number of arguments a frame should have. */ + VALUE binding; + ID id; + ID orig_id; + int line; + const char * file; + short dead; + VALUE self; + VALUE arg_ary; + union { + struct { + struct FRAME *frame; + struct SCOPE *scope; + struct RVarmap *dyna_vars; + } runtime; + struct { + VALUE args; + VALUE locals; + VALUE arg_ary; + } copy; + } info; +} debug_frame_t; + +typedef struct { + VALUE thread_id; + int thnum; + int flags; + enum ctx_stop_reason stop_reason; + int stop_next; + int dest_frame; + int stop_line; + int stop_frame; + int stack_size; + int stack_len; + debug_frame_t *frames; + const char * last_file; + int last_line; + VALUE breakpoint; +} debug_context_t; + +/* variables in ruby_debug.c */ +extern VALUE mDebugger; +extern VALUE rdebug_breakpoints; +extern VALUE rdebug_catchpoints; +extern VALUE rdebug_threads_tbl; + +/* routines in ruby_debug.c */ +extern int filename_cmp(VALUE source, char *file); + +#define IS_STARTED (rdebug_threads_tbl != Qnil) +static inline void +debug_check_started() +{ + if(!IS_STARTED) + { + rb_raise(rb_eRuntimeError, "Debugger.start is not called yet."); + } +} + +static inline int +classname_cmp(VALUE name, VALUE klass) +{ + VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name; + return (klass != Qnil + && rb_str_cmp(class_name, rb_mod_name(klass)) == 0); +} + +/* Breakpoint information */ +enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE}; +enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD}; + +typedef struct { + int id; + enum bp_type type; + VALUE source; + union + { + int line; + ID mid; + } pos; + VALUE expr; + VALUE enabled; + int hit_count; + int hit_value; + enum hit_condition hit_condition; +} debug_breakpoint_t; + +/* routines in breakpoint.c */ +extern int check_breakpoint_expression(VALUE breakpoint, VALUE binding); +extern int check_breakpoint_hit_condition(VALUE breakpoint); +extern VALUE check_breakpoints_by_method(debug_context_t *debug_context, + VALUE klass, ID mid); +extern VALUE check_breakpoints_by_pos(debug_context_t *debug_context, + char *file, int line); +extern VALUE create_breakpoint_from_args(int argc, VALUE *argv, int id); +extern VALUE context_breakpoint(VALUE self); +extern VALUE context_set_breakpoint(int argc, VALUE *argv, VALUE self); +extern VALUE rdebug_add_catchpoint(VALUE self, VALUE value); +extern VALUE debug_catchpoints(VALUE self); +extern VALUE rdebug_remove_breakpoint(VALUE self, VALUE id_value); + +extern void Init_breakpoint(); diff --git a/ext/breakpoint.c b/ext/breakpoint.c new file mode 100644 index 0000000..d3b7b78 --- /dev/null +++ b/ext/breakpoint.c @@ -0,0 +1,579 @@ +#include "ruby_debug.h" + +VALUE rdebug_breakpoints = Qnil; +VALUE rdebug_catchpoints; + +static VALUE cBreakpoint; +static ID idEval; + +static VALUE +eval_expression(VALUE args) +{ + return rb_funcall2(rb_mKernel, idEval, 2, RARRAY(args)->ptr); +} + +int +check_breakpoint_hit_condition(VALUE breakpoint) +{ + debug_breakpoint_t *debug_breakpoint; + + if(breakpoint == Qnil) + return 0; + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + + debug_breakpoint->hit_count++; + if (!Qtrue == debug_breakpoint->enabled) return 0; + switch(debug_breakpoint->hit_condition) + { + case HIT_COND_NONE: + return 1; + case HIT_COND_GE: + { + if(debug_breakpoint->hit_count >= debug_breakpoint->hit_value) + return 1; + break; + } + case HIT_COND_EQ: + { + if(debug_breakpoint->hit_count == debug_breakpoint->hit_value) + return 1; + break; + } + case HIT_COND_MOD: + { + if(debug_breakpoint->hit_count % debug_breakpoint->hit_value == 0) + return 1; + break; + } + } + return 0; +} + +static int +check_breakpoint_by_pos(VALUE breakpoint, char *file, int line) +{ + debug_breakpoint_t *debug_breakpoint; + + if(breakpoint == Qnil) + return 0; + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + if (!Qtrue == debug_breakpoint->enabled) return 0; + if(debug_breakpoint->type != BP_POS_TYPE) + return 0; + if(debug_breakpoint->pos.line != line) + return 0; + if(filename_cmp(debug_breakpoint->source, file)) + return 1; + return 0; +} + +int +check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid) +{ + debug_breakpoint_t *debug_breakpoint; + + if(breakpoint == Qnil) + return 0; + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + if (!Qtrue == debug_breakpoint->enabled) return 0; + if(debug_breakpoint->type != BP_METHOD_TYPE) + return 0; + if(debug_breakpoint->pos.mid != mid) + return 0; + if(classname_cmp(debug_breakpoint->source, klass)) + return 1; + return 0; +} + +VALUE +check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line) +{ + VALUE breakpoint; + int i; + + if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT)) + return Qnil; + + if(check_breakpoint_by_pos(debug_context->breakpoint, file, line)) + return debug_context->breakpoint; + + if(RARRAY(rdebug_breakpoints)->len == 0) + return Qnil; + for(i = 0; i < RARRAY(rdebug_breakpoints)->len; i++) + { + breakpoint = rb_ary_entry(rdebug_breakpoints, i); + if(check_breakpoint_by_pos(breakpoint, file, line)) + return breakpoint; + } + return Qnil; +} + +VALUE +check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid) +{ + VALUE breakpoint; + int i; + + if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT)) + return Qnil; + + if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid)) + return debug_context->breakpoint; + + if(RARRAY(rdebug_breakpoints)->len == 0) + return Qnil; + for(i = 0; i < RARRAY(rdebug_breakpoints)->len; i++) + { + breakpoint = rb_ary_entry(rdebug_breakpoints, i); + if(check_breakpoint_by_method(breakpoint, klass, mid)) + return breakpoint; + } + return Qnil; +} + +int +check_breakpoint_expression(VALUE breakpoint, VALUE binding) +{ + debug_breakpoint_t *debug_breakpoint; + VALUE args, expr_result; + + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + if(NIL_P(debug_breakpoint->expr)) + return 1; + + args = rb_ary_new3(2, debug_breakpoint->expr, binding); + expr_result = rb_protect(eval_expression, args, 0); + return RTEST(expr_result); +} + +static void +breakpoint_mark(void *data) +{ + debug_breakpoint_t *breakpoint; + breakpoint = (debug_breakpoint_t *)data; + rb_gc_mark(breakpoint->source); + rb_gc_mark(breakpoint->expr); +} + +VALUE +create_breakpoint_from_args(int argc, VALUE *argv, int id) +{ + VALUE source, pos, expr; + debug_breakpoint_t *breakpoint; + int type; + + if(rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2) + { + expr = Qnil; + } + type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE; + if(type == BP_POS_TYPE) + source = StringValue(source); + else + pos = StringValue(pos); + breakpoint = ALLOC(debug_breakpoint_t); + breakpoint->id = id; + breakpoint->source = source; + breakpoint->type = type; + if(type == BP_POS_TYPE) + breakpoint->pos.line = FIX2INT(pos); + else + breakpoint->pos.mid = rb_intern(RSTRING(pos)->ptr); + breakpoint->enabled = Qtrue; + breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr); + breakpoint->hit_count = 0; + breakpoint->hit_value = 0; + breakpoint->hit_condition = HIT_COND_NONE; + return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint); +} + +/* + * call-seq: + * Debugger.remove_breakpoint(id) -> breakpoint + * + * Removes breakpoint by its id. + * id is an identificator of a breakpoint. + */ +VALUE +rdebug_remove_breakpoint(VALUE self, VALUE id_value) +{ + int i; + int id; + VALUE breakpoint; + debug_breakpoint_t *debug_breakpoint; + + id = FIX2INT(id_value); + + for( i = 0; i < RARRAY(rdebug_breakpoints)->len; i += 1 ) + { + breakpoint = rb_ary_entry(rdebug_breakpoints, i); + Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); + if(debug_breakpoint->id == id) + { + rb_ary_delete_at(rdebug_breakpoints, i); + return breakpoint; + } + } + return Qnil; +} + +/* + * call-seq: + * Debugger.catchpoints -> hash + * + * Returns a current catchpoints, which is a hash exception names that will + * trigger a debugger when raised. The values are the number of times taht + * catchpoint was hit, initially 0. + */ +VALUE +debug_catchpoints(VALUE self) +{ + debug_check_started(); + + return rdebug_catchpoints; +} + +/* + * call-seq: + * Debugger.catchpoint(string) -> string + * + * Sets catchpoint. Returns the string passed. + */ +VALUE +rdebug_add_catchpoint(VALUE self, VALUE value) +{ + debug_check_started(); + + if (TYPE(value) != T_STRING) { + rb_raise(rb_eTypeError, "value of a catchpoint must be String"); + } + rb_hash_aset(rdebug_catchpoints, rb_str_dup(value), INT2FIX(0)); + return value; +} + +/* + * call-seq: + * context.breakpoint -> breakpoint + * + * Returns a context-specific temporary Breakpoint object. + */ +VALUE +context_breakpoint(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return debug_context->breakpoint; +} + +/* + * call-seq: + * context.set_breakpoint(source, pos, condition = nil) -> breakpoint + * + * Sets a context-specific temporary breakpoint, which can be used to implement + * 'Run to Cursor' debugger function. When this breakpoint is reached, it will be + * cleared out. + * + * source is a name of a file or a class. + * pos is a line number or a method name if source is a class name. + * condition is a string which is evaluated to +true+ when this breakpoint + * is activated. + */ +VALUE +context_set_breakpoint(int argc, VALUE *argv, VALUE self) +{ + VALUE result; + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + result = create_breakpoint_from_args(argc, argv, 0); + debug_context->breakpoint = result; + return result; +} + +/* + * call-seq: + * breakpoint.enabled? + * + * Returns whether breakpoint is enabled or not. + */ +static VALUE +breakpoint_enabled(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return breakpoint->enabled; +} + +/* + * call-seq: + * breakpoint.enabled = bool + * + * Enables or disables breakpoint. + */ +static VALUE +breakpoint_set_enabled(VALUE self, VALUE bool) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return breakpoint->enabled = bool; +} + +/* + * call-seq: + * breakpoint.source -> string + * + * Returns a source of the breakpoint. + */ +static VALUE +breakpoint_source(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return breakpoint->source; +} + +/* + * call-seq: + * breakpoint.source = string + * + * Sets the source of the breakpoint. + */ +static VALUE +breakpoint_set_source(VALUE self, VALUE value) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + breakpoint->source = StringValue(value); + return value; +} + +/* + * call-seq: + * breakpoint.pos -> string or int + * + * Returns the position of this breakpoint. + */ +static VALUE +breakpoint_pos(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + if(breakpoint->type == BP_METHOD_TYPE) + return rb_str_new2(rb_id2name(breakpoint->pos.mid)); + else + return INT2FIX(breakpoint->pos.line); +} + +/* + * call-seq: + * breakpoint.pos = string or int + * + * Sets the position of this breakpoint. + */ +static VALUE +breakpoint_set_pos(VALUE self, VALUE value) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + if(breakpoint->type == BP_METHOD_TYPE) + { + breakpoint->pos.mid = rb_to_id(StringValue(value)); + } + else + breakpoint->pos.line = FIX2INT(value); + return value; +} + +/* + * call-seq: + * breakpoint.expr -> string + * + * Returns a codition expression when this breakpoint should be activated. + */ +static VALUE +breakpoint_expr(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return breakpoint->expr; +} + +/* + * call-seq: + * breakpoint.expr = string | nil + * + * Sets the codition expression when this breakpoint should be activated. + */ +static VALUE +breakpoint_set_expr(VALUE self, VALUE expr) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr); + return expr; +} + +/* + * call-seq: + * breakpoint.id -> int + * + * Returns id of the breakpoint. + */ +static VALUE +breakpoint_id(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return INT2FIX(breakpoint->id); +} + +/* + * call-seq: + * breakpoint.hit_count -> int + * + * Returns the hit count of the breakpoint. + */ +static VALUE +breakpoint_hit_count(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return INT2FIX(breakpoint->hit_count); +} + +/* + * call-seq: + * breakpoint.hit_value -> int + * + * Returns the hit value of the breakpoint. + */ +static VALUE +breakpoint_hit_value(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + return INT2FIX(breakpoint->hit_value); +} + +/* + * call-seq: + * breakpoint.hit_value = int + * + * Sets the hit value of the breakpoint. + */ +static VALUE +breakpoint_set_hit_value(VALUE self, VALUE value) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + breakpoint->hit_value = FIX2INT(value); + return value; +} + +/* + * call-seq: + * breakpoint.hit_condition -> symbol + * + * Returns the hit condition of the breakpoint: + * + * +nil+ if it is an unconditional breakpoint, or + * :greater_or_equal, :equal, :modulo + */ +static VALUE +breakpoint_hit_condition(VALUE self) +{ + debug_breakpoint_t *breakpoint; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + switch(breakpoint->hit_condition) + { + case HIT_COND_GE: + return ID2SYM(rb_intern("greater_or_equal")); + case HIT_COND_EQ: + return ID2SYM(rb_intern("equal")); + case HIT_COND_MOD: + return ID2SYM(rb_intern("modulo")); + case HIT_COND_NONE: + default: + return Qnil; + } +} + +/* + * call-seq: + * breakpoint.hit_condition = symbol + * + * Sets the hit condition of the breakpoint which must be one of the following values: + * + * +nil+ if it is an unconditional breakpoint, or + * :greater_or_equal(:ge), :equal(:eq), :modulo(:mod) + */ +static VALUE +breakpoint_set_hit_condition(VALUE self, VALUE value) +{ + debug_breakpoint_t *breakpoint; + ID id_value; + + Data_Get_Struct(self, debug_breakpoint_t, breakpoint); + id_value = rb_to_id(value); + + if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value) + breakpoint->hit_condition = HIT_COND_GE; + else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value) + breakpoint->hit_condition = HIT_COND_EQ; + else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value) + breakpoint->hit_condition = HIT_COND_MOD; + else + rb_raise(rb_eArgError, "Invalid condition parameter"); + return value; +} + +/* + * Document-class: Breakpoint + * + * == Summary + * + * This class represents a breakpoint. It defines position of the breakpoint and + * condition when this breakpoint should be triggered. + */ +void +Init_breakpoint() +{ + cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject); + rb_define_method(cBreakpoint, "enabled=", breakpoint_set_enabled, 1); + rb_define_method(cBreakpoint, "enabled?", breakpoint_enabled, 0); + rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0); + rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1); + rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0); + rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1); + rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0); + rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0); + rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1); + rb_define_method(cBreakpoint, "id", breakpoint_id, 0); + rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0); + rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1); + rb_define_method(cBreakpoint, "source", breakpoint_source, 0); + rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1); + idEval = rb_intern("eval"); + rdebug_catchpoints = rb_hash_new(); + +} + + diff --git a/ext/extconf.rb b/ext/extconf.rb new file mode 100644 index 0000000..1bb8e40 --- /dev/null +++ b/ext/extconf.rb @@ -0,0 +1,20 @@ +require "mkmf" + +if RUBY_VERSION >= "1.9" + if RUBY_RELEASE_DATE < "2005-03-17" + STDERR.print("Ruby version is too old\n") + exit(1) + end +elsif RUBY_VERSION >= "1.8" + if RUBY_RELEASE_DATE < "2005-03-22" + STDERR.print("Ruby version is too old\n") + exit(1) + end +else + STDERR.print("Ruby version is too old\n") + exit(1) +end + +# Temporary: to turn off optimization +# $CFLAGS='-fno-strict-aliasing -g -fPIC' +create_makefile("ruby_debug") diff --git a/ext/ruby_debug.c b/ext/ruby_debug.c new file mode 100644 index 0000000..503329a --- /dev/null +++ b/ext/ruby_debug.c @@ -0,0 +1,2322 @@ +#include "ruby_debug.h" + +#include +#include +#include +#include +#include + +#define DEBUG_VERSION "0.10.4" + + +#ifdef _WIN32 +struct FRAME { + VALUE self; + int argc; + ID last_func; + ID orig_func; + VALUE last_class; + struct FRAME *prev; + struct FRAME *tmp; + struct RNode *node; + int iter; + int flags; + unsigned long uniq; +}; + +struct SCOPE { + struct RBasic super; + ID *local_tbl; + VALUE *local_vars; + int flags; +}; + +struct RVarmap { + struct RBasic super; + ID id; + VALUE val; + struct RVarmap *next; +}; + +RUBY_EXTERN struct SCOPE *ruby_scope; +RUBY_EXTERN struct FRAME *ruby_frame; +RUBY_EXTERN struct RVarmap *ruby_dyna_vars; +#else +#include +#endif + +#define FRAME_N(n) (&debug_context->frames[debug_context->stack_size-(n)-1]) +#define GET_FRAME (FRAME_N(check_frame_number(debug_context, frame))) + +#ifndef min +#define min(x,y) ((x) < (y) ? (x) : (y)) +#endif + +#define STACK_SIZE_INCREMENT 128 + +typedef struct { + st_table *tbl; +} threads_table_t; + +static VALUE tracing = Qfalse; +static VALUE locker = Qnil; +static VALUE post_mortem = Qfalse; +static VALUE keep_frame_binding = Qfalse; +static VALUE debug = Qfalse; +static VALUE track_frame_args = Qfalse; + +static VALUE last_context = Qnil; +static VALUE last_thread = Qnil; +static debug_context_t *last_debug_context = NULL; + +VALUE rdebug_threads_tbl = Qnil; /* Context for each of the threads */ +VALUE mDebugger; /* Ruby Debugger Module object */ + +static VALUE cThreadsTable; +static VALUE cContext; +static VALUE cDebugThread; + +static VALUE rb_mObjectSpace; + +static ID idAtBreakpoint; +static ID idAtCatchpoint; +static ID idAtLine; +static ID idAtReturn; +static ID idAtTracing; +static ID idList; + +static int start_count = 0; +static int thnum_max = 0; +static int bkp_count = 0; +static int last_debugged_thnum = -1; +static unsigned long last_check = 0; +static unsigned long hook_count = 0; + +static VALUE create_binding(VALUE); +static VALUE debug_stop(VALUE); +static void save_current_position(debug_context_t *); +static VALUE context_copy_args(debug_frame_t *); +static VALUE context_copy_locals(debug_frame_t *); +static void context_suspend_0(debug_context_t *); +static void context_resume_0(debug_context_t *); +static void copy_scalar_args(debug_frame_t *); + +typedef struct locked_thread_t { + VALUE thread_id; + struct locked_thread_t *next; +} locked_thread_t; + +static locked_thread_t *locked_head = NULL; +static locked_thread_t *locked_tail = NULL; + +/* "Step", "Next" and "Finish" do their work by saving information + about where to stop next. reset_stopping_points removes/resets this + information. */ +inline static void +reset_stepping_stop_points(debug_context_t *debug_context) +{ + debug_context->dest_frame = -1; + debug_context->stop_line = -1; + debug_context->stop_next = -1; +} + +inline static VALUE +real_class(VALUE klass) +{ + if (klass) { + if (TYPE(klass) == T_ICLASS) { + return RBASIC(klass)->klass; + } + else if (FL_TEST(klass, FL_SINGLETON)) { + return rb_iv_get(klass, "__attached__"); + } + } + return klass; +} + +inline static void * +ruby_method_ptr(VALUE class, ID meth_id) +{ + NODE *body, *method; + st_lookup(RCLASS(class)->m_tbl, meth_id, (st_data_t *)&body); + method = (NODE *)body->u2.value; + return (void *)method->u1.value; +} + +inline static VALUE +ref2id(VALUE obj) +{ + return rb_obj_id(obj); +} + +static VALUE +id2ref_unprotected(VALUE id) +{ + typedef VALUE (*id2ref_func_t)(VALUE, VALUE); + static id2ref_func_t f_id2ref = NULL; + if(f_id2ref == NULL) + { + f_id2ref = (id2ref_func_t)ruby_method_ptr(rb_mObjectSpace, rb_intern("_id2ref")); + } + return f_id2ref(rb_mObjectSpace, id); +} + +static VALUE +id2ref_error() +{ + if(debug == Qtrue) + rb_p(ruby_errinfo); + return Qnil; +} + +static VALUE +id2ref(VALUE id) +{ + return rb_rescue(id2ref_unprotected, id, id2ref_error, 0); +} + +inline static VALUE +context_thread_0(debug_context_t *debug_context) +{ + return id2ref(debug_context->thread_id); +} + +static int +is_in_locked(VALUE thread_id) +{ + locked_thread_t *node; + + if(!locked_head) + return 0; + + for(node = locked_head; node != locked_tail; node = node->next) + { + if(node->thread_id == thread_id) return 1; + } + return 0; +} + +static void +add_to_locked(VALUE thread) +{ + locked_thread_t *node; + VALUE thread_id = ref2id(thread); + + if(is_in_locked(thread_id)) + return; + + node = ALLOC(locked_thread_t); + node->thread_id = thread_id; + node->next = NULL; + if(locked_tail) + locked_tail->next = node; + locked_tail = node; + if(!locked_head) + locked_head = node; +} + +static VALUE +remove_from_locked() +{ + VALUE thread; + locked_thread_t *node; + + if(locked_head == NULL) + return Qnil; + node = locked_head; + locked_head = locked_head->next; + if(locked_tail == node) + locked_tail = NULL; + thread = id2ref(node->thread_id); + xfree(node); + return thread; +} + +static int +threads_table_mark_keyvalue(VALUE key, VALUE value, int dummy) +{ + rb_gc_mark(value); + return ST_CONTINUE; +} + +static void +threads_table_mark(void* data) +{ + threads_table_t *threads_table = (threads_table_t*)data; + st_foreach(threads_table->tbl, threads_table_mark_keyvalue, 0); +} + +static void +threads_table_free(void* data) +{ + threads_table_t *threads_table = (threads_table_t*)data; + st_free_table(threads_table->tbl); + xfree(threads_table); +} + +static VALUE +threads_table_create() +{ + threads_table_t *threads_table; + + threads_table = ALLOC(threads_table_t); + threads_table->tbl = st_init_numtable(); + return Data_Wrap_Struct(cThreadsTable, threads_table_mark, threads_table_free, threads_table); +} + +static int +threads_table_clear_i(VALUE key, VALUE value, VALUE dummy) +{ + return ST_DELETE; +} + +static void +threads_table_clear(VALUE table) +{ + threads_table_t *threads_table; + + Data_Get_Struct(table, threads_table_t, threads_table); + st_foreach(threads_table->tbl, threads_table_clear_i, 0); +} + +static VALUE +is_thread_alive(VALUE thread) +{ + typedef VALUE (*thread_alive_func_t)(VALUE); + static thread_alive_func_t f_thread_alive = NULL; + if(!f_thread_alive) + { + f_thread_alive = (thread_alive_func_t)ruby_method_ptr(rb_cThread, rb_intern("alive?")); + } + return f_thread_alive(thread); +} + +static int +threads_table_check_i(VALUE key, VALUE value, VALUE dummy) +{ + VALUE thread; + + thread = id2ref(key); + if(!rb_obj_is_kind_of(thread, rb_cThread)) + { + return ST_DELETE; + } + if(rb_protect(is_thread_alive, thread, 0) != Qtrue) + { + return ST_DELETE; + } + return ST_CONTINUE; +} + +static void +check_thread_contexts() +{ + threads_table_t *threads_table; + + Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table); + st_foreach(threads_table->tbl, threads_table_check_i, 0); +} + +/* + * call-seq: + * Debugger.started? -> bool + * + * Returns +true+ the debugger is started. + */ +static VALUE +debug_is_started(VALUE self) +{ + return IS_STARTED ? Qtrue : Qfalse; +} + +static void +debug_context_mark(void *data) +{ + debug_frame_t *frame; + int i; + + debug_context_t *debug_context = (debug_context_t *)data; + for(i = 0; i < debug_context->stack_size; i++) + { + frame = &(debug_context->frames[i]); + rb_gc_mark(frame->binding); + rb_gc_mark(frame->self); + rb_gc_mark(frame->arg_ary); + if(frame->dead) + { + rb_gc_mark(frame->info.copy.locals); + rb_gc_mark(frame->info.copy.args); + } + } + rb_gc_mark(debug_context->breakpoint); +} + +static void +debug_context_free(void *data) +{ + debug_context_t *debug_context = (debug_context_t *)data; + xfree(debug_context->frames); +} + +static VALUE +debug_context_create(VALUE thread) +{ + debug_context_t *debug_context; + + debug_context = ALLOC(debug_context_t); + debug_context-> thnum = ++thnum_max; + + debug_context->last_file = NULL; + debug_context->last_line = 0; + debug_context->flags = 0; + + debug_context->stop_next = -1; + debug_context->dest_frame = -1; + debug_context->stop_line = -1; + debug_context->stop_frame = -1; + debug_context->stop_reason = CTX_STOP_NONE; + debug_context->stack_len = STACK_SIZE_INCREMENT; + debug_context->frames = ALLOC_N(debug_frame_t, STACK_SIZE_INCREMENT); + debug_context->stack_size = 0; + debug_context->thread_id = ref2id(thread); + debug_context->breakpoint = Qnil; + if(rb_obj_class(thread) == cDebugThread) + CTX_FL_SET(debug_context, CTX_FL_IGNORE); + return Data_Wrap_Struct(cContext, debug_context_mark, debug_context_free, debug_context); +} + +static VALUE +debug_context_dup(debug_context_t *debug_context) +{ + debug_context_t *new_debug_context; + debug_frame_t *new_frame, *old_frame; + int i; + + new_debug_context = ALLOC(debug_context_t); + memcpy(new_debug_context, debug_context, sizeof(debug_context_t)); + new_debug_context->stop_next = -1; + new_debug_context->dest_frame = -1; + new_debug_context->stop_line = -1; + new_debug_context->stop_frame = -1; + new_debug_context->breakpoint = Qnil; + CTX_FL_SET(new_debug_context, CTX_FL_DEAD); + new_debug_context->frames = ALLOC_N(debug_frame_t, debug_context->stack_size); + new_debug_context->stack_len = debug_context->stack_size; + memcpy(new_debug_context->frames, debug_context->frames, sizeof(debug_frame_t) * debug_context->stack_size); + for(i = 0; i < debug_context->stack_size; i++) + { + new_frame = &(new_debug_context->frames[i]); + old_frame = &(debug_context->frames[i]); + new_frame->dead = 1; + new_frame->info.copy.args = context_copy_args(old_frame); + new_frame->info.copy.locals = context_copy_locals(old_frame); + } + return Data_Wrap_Struct(cContext, debug_context_mark, debug_context_free, new_debug_context); +} + +static void +thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_context) +{ + threads_table_t *threads_table; + VALUE thread_id; + debug_context_t *l_debug_context; + + debug_check_started(); + + if(last_thread == thread && last_context != Qnil) + { + *context = last_context; + if(debug_context) + *debug_context = last_debug_context; + return; + } + thread_id = ref2id(thread); + Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table); + if(!st_lookup(threads_table->tbl, thread_id, context)) + { + *context = debug_context_create(thread); + st_insert(threads_table->tbl, thread_id, *context); + } + + Data_Get_Struct(*context, debug_context_t, l_debug_context); + if(debug_context) + *debug_context = l_debug_context; + + last_thread = thread; + last_context = *context; + last_debug_context = l_debug_context; +} + +static VALUE +call_at_line_unprotected(VALUE args) +{ + VALUE context; + context = *RARRAY(args)->ptr; + return rb_funcall2(context, idAtLine, RARRAY(args)->len - 1, RARRAY(args)->ptr + 1); +} + +static VALUE +call_at_line(VALUE context, debug_context_t *debug_context, VALUE file, VALUE line) +{ + VALUE args; + + last_debugged_thnum = debug_context->thnum; + save_current_position(debug_context); + + args = rb_ary_new3(3, context, file, line); + return rb_protect(call_at_line_unprotected, args, 0); +} + +static void +save_call_frame(rb_event_t event, VALUE self, char *file, int line, ID mid, debug_context_t *debug_context) +{ + VALUE binding; + debug_frame_t *debug_frame; + int frame_n; + + binding = self && RTEST(keep_frame_binding)? create_binding(self) : Qnil; + + frame_n = debug_context->stack_size++; + if(frame_n >= debug_context->stack_len) + { + debug_context->stack_len += STACK_SIZE_INCREMENT; + debug_context->frames = REALLOC_N(debug_context->frames, debug_frame_t, debug_context->stack_len); + } + debug_frame = &debug_context->frames[frame_n]; + debug_frame->argc = ruby_frame->argc; + debug_frame->file = file; + debug_frame->line = line; + debug_frame->binding = binding; + debug_frame->id = mid; + debug_frame->orig_id = mid; + debug_frame->dead = 0; + debug_frame->self = self; + debug_frame->arg_ary = Qnil; + debug_frame->info.runtime.frame = ruby_frame; + debug_frame->info.runtime.scope = ruby_scope; + debug_frame->info.runtime.dyna_vars = event == RUBY_EVENT_LINE ? ruby_dyna_vars : NULL; + if (RTEST(track_frame_args)) + copy_scalar_args(debug_frame); +} + + +#if defined DOSISH +#define isdirsep(x) ((x) == '/' || (x) == '\\') +#else +#define isdirsep(x) ((x) == '/') +#endif + +int +filename_cmp(VALUE source, char *file) +{ + char *source_ptr, *file_ptr; + int s_len, f_len, min_len; + int s,f; + int dirsep_flag = 0; + + s_len = RSTRING(source)->len; + f_len = strlen(file); + min_len = min(s_len, f_len); + + source_ptr = RSTRING(source)->ptr; + file_ptr = file; + + for( s = s_len - 1, f = f_len - 1; s >= s_len - min_len && f >= f_len - min_len; s--, f-- ) + { + if((source_ptr[s] == '.' || file_ptr[f] == '.') && dirsep_flag) + return 1; + if(isdirsep(source_ptr[s]) && isdirsep(file_ptr[f])) + dirsep_flag = 1; + else if(source_ptr[s] != file_ptr[f]) + return 0; + } + return 1; +} + +/* + * This is a NASTY HACK. For some reasons rb_f_binding is declared + * static in eval.c. So we create a cons up call to binding in C. + */ +static VALUE +create_binding(VALUE self) +{ + typedef VALUE (*bind_func_t)(VALUE); + static bind_func_t f_binding = NULL; + + if(f_binding == NULL) + { + f_binding = (bind_func_t)ruby_method_ptr(rb_mKernel, rb_intern("binding")); + } + return f_binding(self); +} + +inline static debug_frame_t * +get_top_frame(debug_context_t *debug_context) +{ + if(debug_context->stack_size == 0) + return NULL; + else + return &(debug_context->frames[debug_context->stack_size-1]); +} + +inline static void +save_top_binding(debug_context_t *debug_context, VALUE binding) +{ + debug_frame_t *debug_frame; + debug_frame = get_top_frame(debug_context); + if(debug_frame) + debug_frame->binding = binding; +} + +inline static void +set_frame_source(rb_event_t event, debug_context_t *debug_context, VALUE self, char *file, int line, ID mid) +{ + debug_frame_t *top_frame; + top_frame = get_top_frame(debug_context); + if(top_frame) + { + top_frame->self = self; + top_frame->file = file; + top_frame->line = line; + top_frame->id = mid; + top_frame->info.runtime.dyna_vars = event == RUBY_EVENT_C_CALL ? NULL : ruby_dyna_vars; + } +} + +inline static void +reset_frame_mid(debug_context_t *debug_context) +{ + debug_frame_t *top_frame; + top_frame = get_top_frame(debug_context); + if(top_frame) + { + top_frame->id = 0; + } +} + +static void +save_current_position(debug_context_t *debug_context) +{ + debug_frame_t *debug_frame; + + debug_frame = get_top_frame(debug_context); + if(!debug_frame) return; + debug_context->last_file = debug_frame->file; + debug_context->last_line = debug_frame->line; + CTX_FL_UNSET(debug_context, CTX_FL_ENABLE_BKPT); + CTX_FL_UNSET(debug_context, CTX_FL_STEPPED); + CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE); +} + +inline static char * +get_event_name(rb_event_t event) +{ + switch (event) { + case RUBY_EVENT_LINE: + return "line"; + case RUBY_EVENT_CLASS: + return "class"; + case RUBY_EVENT_END: + return "end"; + case RUBY_EVENT_CALL: + return "call"; + case RUBY_EVENT_RETURN: + return "return"; + case RUBY_EVENT_C_CALL: + return "c-call"; + case RUBY_EVENT_C_RETURN: + return "c-return"; + case RUBY_EVENT_RAISE: + return "raise"; + default: + return "unknown"; + } +} + +inline static int +c_call_new_frame_p(VALUE klass, ID mid) +{ + klass = real_class(klass); + if(rb_block_given_p()) return 1; + if(klass == rb_cProc || klass == rb_mKernel || klass == rb_cModule) return 1; + return 0; +} + +static void +debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass) +{ + VALUE thread, context; + VALUE breakpoint = Qnil, binding = Qnil; + debug_context_t *debug_context; + char *file = NULL; + int line = 0, moved = 0; + + hook_count++; + + if (mid == ID_ALLOCATOR) return; + + thread = rb_thread_current(); + thread_context_lookup(thread, &context, &debug_context); + + /* return if thread is marked as 'ignored'. + debugger's threads are marked this way + */ + if(CTX_FL_TEST(debug_context, CTX_FL_IGNORE)) return; + + while(1) + { + /* halt execution of the current thread if the debugger + is activated in another + */ + while(locker != Qnil && locker != thread) + { + add_to_locked(thread); + rb_thread_stop(); + } + + /* stop the current thread if it's marked as suspended */ + if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND) && locker != thread) + { + CTX_FL_SET(debug_context, CTX_FL_WAS_RUNNING); + rb_thread_stop(); + } + else break; + } + + /* return if the current thread is the locker */ + if(locker != Qnil) return; + + /* only the current thread can proceed */ + locker = thread; + + /* ignore a skipped section of code */ + if(CTX_FL_TEST(debug_context, CTX_FL_SKIPPED)) goto cleanup; + + if(node) + { + file = node->nd_file; + line = nd_line(node); + + if(debug == Qtrue) + fprintf(stderr, "%s:%d [%s] %s\n", file, line, get_event_name(event), rb_id2name(mid)); + + /* There can be many event calls per line, but we only want + *one* breakpoint per line. */ + if(debug_context->last_line != line || debug_context->last_file == NULL || + strcmp(debug_context->last_file, file) != 0) + { + CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT); + moved = 1; + } + else if(event == RUBY_EVENT_LINE) + { + /* There are two line-event trace hook calls per IF node - one + before the expression eval an done afterwards. + */ + /* FIXME: the static variable can't be safely used here, since this method + is re-entrant by multiple threads. If we want to provide this kind of functionality + if_eval_event variable must be moved to debug_context structure. + */ + /* + static int if_eval_event = 0; + if_eval_event = (NODE_IF == nd_type(node)) ? !if_eval_event : 0; + if (!if_eval_event) + { + CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT); + } + */ + } + } + else if(event != RUBY_EVENT_RETURN && event != RUBY_EVENT_C_RETURN) + { + if(debug == Qtrue) + fprintf(stderr, "nodeless [%s] %s\n", get_event_name(event), rb_id2name(mid)); + goto cleanup; + } + else + { + if(debug == Qtrue) + fprintf(stderr, "nodeless [%s] %s\n", get_event_name(event), rb_id2name(mid)); + } + + if(event != RUBY_EVENT_LINE) + CTX_FL_SET(debug_context, CTX_FL_STEPPED); + + switch(event) + { + case RUBY_EVENT_LINE: + { + + if(debug_context->stack_size == 0) + save_call_frame(event, self, file, line, mid, debug_context); + else + set_frame_source(event, debug_context, self, file, line, mid); + + if(RTEST(tracing) || CTX_FL_TEST(debug_context, CTX_FL_TRACING)) + rb_funcall(context, idAtTracing, 2, rb_str_new2(file), INT2FIX(line)); + + if(debug_context->dest_frame == -1 || + debug_context->stack_size == debug_context->dest_frame) + { + if(moved || !CTX_FL_TEST(debug_context, CTX_FL_FORCE_MOVE)) + debug_context->stop_next--; + if(debug_context->stop_next < 0) + debug_context->stop_next = -1; + if(moved || (CTX_FL_TEST(debug_context, CTX_FL_STEPPED) && + !CTX_FL_TEST(debug_context, CTX_FL_FORCE_MOVE))) + { + debug_context->stop_line--; + CTX_FL_UNSET(debug_context, CTX_FL_STEPPED); + } + } + else if(debug_context->stack_size < debug_context->dest_frame) + { + debug_context->stop_next = 0; + } + + if(debug_context->stop_next == 0 || debug_context->stop_line == 0 || + (breakpoint = check_breakpoints_by_pos(debug_context, file, line)) != Qnil) + { + binding = self? create_binding(self) : Qnil; + save_top_binding(debug_context, binding); + + debug_context->stop_reason = CTX_STOP_STEP; + + /* check breakpoint expression */ + if(breakpoint != Qnil) + { + if(!check_breakpoint_expression(breakpoint, binding)) + break; + if(!check_breakpoint_hit_condition(breakpoint)) + break; + if(breakpoint != debug_context->breakpoint) + { + debug_context->stop_reason = CTX_STOP_BREAKPOINT; + rb_funcall(context, idAtBreakpoint, 1, breakpoint); + } + else + debug_context->breakpoint = Qnil; + } + + reset_stepping_stop_points(debug_context); + call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line)); + } + break; + } + case RUBY_EVENT_CALL: + { + save_call_frame(event, self, file, line, mid, debug_context); + breakpoint = check_breakpoints_by_method(debug_context, klass, mid); + if(breakpoint != Qnil) + { + debug_frame_t *debug_frame; + debug_frame = get_top_frame(debug_context); + if(debug_frame) + binding = debug_frame->binding; + if(NIL_P(binding) && self) + binding = create_binding(self); + save_top_binding(debug_context, binding); + + if(!check_breakpoint_expression(breakpoint, binding)) + break; + if(!check_breakpoint_hit_condition(breakpoint)) + break; + if(breakpoint != debug_context->breakpoint) + { + debug_context->stop_reason = CTX_STOP_BREAKPOINT; + rb_funcall(context, idAtBreakpoint, 1, breakpoint); + } + else + debug_context->breakpoint = Qnil; + call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line)); + } + break; + } + case RUBY_EVENT_C_CALL: + { + if(c_call_new_frame_p(klass, mid)) + save_call_frame(event, self, file, line, mid, debug_context); + else + set_frame_source(event, debug_context, self, file, line, mid); + break; + } + case RUBY_EVENT_C_RETURN: + { + /* note if a block is given we fall through! */ + if(!node || !c_call_new_frame_p(klass, mid)) + break; + } + case RUBY_EVENT_RETURN: + case RUBY_EVENT_END: + { + if(debug_context->stack_size == debug_context->stop_frame) + { + debug_context->stop_next = 1; + debug_context->stop_frame = 0; + /* NOTE: can't use call_at_line function here to trigger a debugger event. + this can lead to segfault. We should only unroll the stack on this event. + */ + } + while(debug_context->stack_size > 0) + { + debug_context->stack_size--; + if(debug_context->frames[debug_context->stack_size].orig_id == mid) + break; + } + CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT); + break; + } + case RUBY_EVENT_CLASS: + { + reset_frame_mid(debug_context); + save_call_frame(event, self, file, line, mid, debug_context); + break; + } + case RUBY_EVENT_RAISE: + { + VALUE ancestors; + VALUE expn_class, aclass; + int i; + + set_frame_source(event, debug_context, self, file, line, mid); + + if(post_mortem == Qtrue && self) + { + binding = create_binding(self); + rb_ivar_set(ruby_errinfo, rb_intern("@__debug_file"), rb_str_new2(file)); + rb_ivar_set(ruby_errinfo, rb_intern("@__debug_line"), INT2FIX(line)); + rb_ivar_set(ruby_errinfo, rb_intern("@__debug_binding"), binding); + rb_ivar_set(ruby_errinfo, rb_intern("@__debug_context"), debug_context_dup(debug_context)); + } + + expn_class = rb_obj_class(ruby_errinfo); + + /* This code goes back to the earliest days of ruby-debug. It + tends to disallow catching an exception via the + "catchpoint" command. To address this one possiblilty is to + move this after testing for catchponts. Kent however thinks + there may be a misfeature in Ruby's eval.c: the problem was + in the fact that Ruby doesn't reset exception flag on the + current thread before it calls a notification handler. + + See also the #ifdef'd code below as well. + */ +#ifdef NORMAL_CODE + if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) ) + { + debug_stop(mDebugger); + break; + } +#endif + + if (rdebug_catchpoints == Qnil || + RHASH(rdebug_catchpoints)->tbl->num_entries == 0) + break; + + ancestors = rb_mod_ancestors(expn_class); + for(i = 0; i < RARRAY(ancestors)->len; i++) + { + VALUE mod_name; + VALUE hit_count; + + aclass = rb_ary_entry(ancestors, i); + mod_name = rb_mod_name(aclass); + hit_count = rb_hash_aref(rdebug_catchpoints, mod_name); + if(hit_count != Qnil) + { + hit_count = INT2FIX(FIX2INT(rb_hash_aref(rdebug_catchpoints, + mod_name)+1)); + rb_hash_aset(rdebug_catchpoints, mod_name, hit_count); + debug_context->stop_reason = CTX_STOP_CATCHPOINT; + rb_funcall(context, idAtCatchpoint, 1, ruby_errinfo); + if(self && binding == Qnil) + binding = create_binding(self); + save_top_binding(debug_context, binding); + call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line)); + break; + } + } + + /* If we stop the debugger, we may not be able to trace into + code that has an exception handler wrapped around it. So + the alternative is to force the user to do his own + Debugger.stop. */ +#ifdef NORMAL_CODE_MOVING_AFTER_ + if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) ) + { + debug_stop(mDebugger); + break; + } +#endif + + break; + } + } + + cleanup: + + debug_context->stop_reason = CTX_STOP_NONE; + + /* check that all contexts point to alive threads */ + if(hook_count - last_check > 3000) + { + check_thread_contexts(); + last_check = hook_count; + } + + /* release a lock */ + locker = Qnil; + /* let the next thread to run */ + thread = remove_from_locked(); + if(thread != Qnil) + rb_thread_run(thread); +} + +static VALUE +debug_stop_i(VALUE self) +{ + if(IS_STARTED) + debug_stop(self); + return Qnil; +} + +/* + * call-seq: + * Debugger.start_ -> bool + * Debugger.start_ { ... } -> bool + * + * This method is internal and activates the debugger. Use + * Debugger.start (from lib/ruby-debug-base.rb) instead. + * + * The return value is the value of !Debugger.started? before + * issuing the +start+; That is, +true+ is returned, unless debugger + * was previously started. + + * If a block is given, it starts debugger and yields to block. When + * the block is finished executing it stops the debugger with + * Debugger.stop method. Inside the block you will probably want to + * have a call to Debugger.debugger. For example: + * Debugger.start{debugger; foo} # Stop inside of foo + * + * Also, ruby-debug only allows + * one invocation of debugger at a time; nested Debugger.start's + * have no effect and you can't use this inside the debugger itself. + * + * Note that if you want to completely remove the debugger hook, + * you must call Debugger.stop as many times as you called + * Debugger.start method. + */ +static VALUE +debug_start(VALUE self) +{ + VALUE result; + start_count++; + + if(IS_STARTED) + result = Qfalse; + else + { + locker = Qnil; + rdebug_breakpoints = rb_ary_new(); + rdebug_catchpoints = rb_hash_new(); + rdebug_threads_tbl = threads_table_create(); + + rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL); + result = Qtrue; + } + + if(rb_block_given_p()) + rb_ensure(rb_yield, self, debug_stop_i, self); + + return result; +} + +/* + * call-seq: + * Debugger.stop -> bool + * + * This method disables the debugger. It returns +true+ if the debugger is disabled, + * otherwise it returns +false+. + * + * Note that if you want to complete remove the debugger hook, + * you must call Debugger.stop as many times as you called + * Debugger.start method. + */ +static VALUE +debug_stop(VALUE self) +{ + debug_check_started(); + + start_count--; + if(start_count) + return Qfalse; + + rb_remove_event_hook(debug_event_hook); + + locker = Qnil; + rdebug_breakpoints = Qnil; + rdebug_threads_tbl = Qnil; + + return Qtrue; +} + +static int +find_last_context_func(VALUE key, VALUE value, VALUE *result) +{ + debug_context_t *debug_context; + Data_Get_Struct(value, debug_context_t, debug_context); + if(debug_context->thnum == last_debugged_thnum) + { + *result = value; + return ST_STOP; + } + return ST_CONTINUE; +} + +/* + * call-seq: + * Debugger.last_interrupted -> context + * + * Returns last debugged context. + */ +static VALUE +debug_last_interrupted(VALUE self) +{ + VALUE result = Qnil; + threads_table_t *threads_table; + + debug_check_started(); + + Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table); + + st_foreach(threads_table->tbl, find_last_context_func, (st_data_t)&result); + return result; +} + +/* + * call-seq: + * Debugger.current_context -> context + * + * Returns current context. + * Note: Debugger.current_context.thread == Thread.current + */ +static VALUE +debug_current_context(VALUE self) +{ + VALUE thread, context; + + debug_check_started(); + + thread = rb_thread_current(); + thread_context_lookup(thread, &context, NULL); + + return context; +} + +/* + * call-seq: + * Debugger.thread_context(thread) -> context + * + * Returns context of the thread passed as an argument. + */ +static VALUE +debug_thread_context(VALUE self, VALUE thread) +{ + VALUE context; + + debug_check_started(); + thread_context_lookup(thread, &context, NULL); + return context; +} + +/* + * call-seq: + * Debugger.contexts -> array + * + * Returns an array of all contexts. + */ +static VALUE +debug_contexts(VALUE self) +{ + volatile VALUE list; + volatile VALUE new_list; + VALUE thread, context; + threads_table_t *threads_table; + debug_context_t *debug_context; + int i; + + debug_check_started(); + + new_list = rb_ary_new(); + list = rb_funcall(rb_cThread, idList, 0); + for(i = 0; i < RARRAY(list)->len; i++) + { + thread = rb_ary_entry(list, i); + thread_context_lookup(thread, &context, NULL); + rb_ary_push(new_list, context); + } + threads_table_clear(rdebug_threads_tbl); + Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table); + for(i = 0; i < RARRAY(new_list)->len; i++) + { + context = rb_ary_entry(new_list, i); + Data_Get_Struct(context, debug_context_t, debug_context); + st_insert(threads_table->tbl, debug_context->thread_id, context); + } + + return new_list; +} + +/* + * call-seq: + * Debugger.suspend -> Debugger + * + * Suspends all contexts. + */ +static VALUE +debug_suspend(VALUE self) +{ + VALUE current, context; + VALUE saved_crit; + VALUE context_list; + debug_context_t *debug_context; + int i; + + debug_check_started(); + + saved_crit = rb_thread_critical; + rb_thread_critical = Qtrue; + context_list = debug_contexts(self); + thread_context_lookup(rb_thread_current(), ¤t, NULL); + + for(i = 0; i < RARRAY(context_list)->len; i++) + { + context = rb_ary_entry(context_list, i); + if(current == context) + continue; + Data_Get_Struct(context, debug_context_t, debug_context); + context_suspend_0(debug_context); + } + rb_thread_critical = saved_crit; + + if(rb_thread_critical == Qfalse) + rb_thread_schedule(); + + return self; +} + +/* + * call-seq: + * Debugger.resume -> Debugger + * + * Resumes all contexts. + */ +static VALUE +debug_resume(VALUE self) +{ + VALUE current, context; + VALUE saved_crit; + VALUE context_list; + debug_context_t *debug_context; + int i; + + debug_check_started(); + + saved_crit = rb_thread_critical; + rb_thread_critical = Qtrue; + context_list = debug_contexts(self); + + thread_context_lookup(rb_thread_current(), ¤t, NULL); + for(i = 0; i < RARRAY(context_list)->len; i++) + { + context = rb_ary_entry(context_list, i); + if(current == context) + continue; + Data_Get_Struct(context, debug_context_t, debug_context); + context_resume_0(debug_context); + } + rb_thread_critical = saved_crit; + + rb_thread_schedule(); + + return self; +} + +/* + * call-seq: + * Debugger.tracing -> bool + * + * Returns +true+ if the global tracing is activated. + */ +static VALUE +debug_tracing(VALUE self) +{ + return tracing; +} + +/* + * call-seq: + * Debugger.tracing = bool + * + * Sets the global tracing flag. + */ +static VALUE +debug_set_tracing(VALUE self, VALUE value) +{ + tracing = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* + * call-seq: + * Debugger.post_mortem? -> bool + * + * Returns +true+ if post-moterm debugging is enabled. + */ +static VALUE +debug_post_mortem(VALUE self) +{ + return post_mortem; +} + +/* + * call-seq: + * Debugger.post_mortem = bool + * + * Sets post-moterm flag. + * FOR INTERNAL USE ONLY. + */ +static VALUE +debug_set_post_mortem(VALUE self, VALUE value) +{ + debug_check_started(); + + post_mortem = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* + * call-seq: + * Debugger.track_fame_args? -> bool + * + * Returns +true+ if the debugger track frame argument values on calls. + */ +static VALUE +debug_track_frame_args(VALUE self) +{ + return track_frame_args; +} + +/* + * call-seq: + * Debugger.track_frame_args = bool + * + * Setting to +true+ will make the debugger save argument info on calls. + */ +static VALUE +debug_set_track_frame_args(VALUE self, VALUE value) +{ + track_frame_args = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* + * call-seq: + * Debugger.keep_frame_binding? -> bool + * + * Returns +true+ if the debugger will collect frame bindings. + */ +static VALUE +debug_keep_frame_binding(VALUE self) +{ + return keep_frame_binding; +} + +/* + * call-seq: + * Debugger.keep_frame_binding = bool + * + * Setting to +true+ will make the debugger create frame bindings. + */ +static VALUE +debug_set_keep_frame_binding(VALUE self, VALUE value) +{ + keep_frame_binding = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* :nodoc: */ +static VALUE +debug_debug(VALUE self) +{ + return debug; +} + +/* :nodoc: */ +static VALUE +debug_set_debug(VALUE self, VALUE value) +{ + debug = RTEST(value) ? Qtrue : Qfalse; + return value; +} + +/* :nodoc: */ +static VALUE +debug_thread_inherited(VALUE klass) +{ + rb_raise(rb_eRuntimeError, "Can't inherite Debugger::DebugThread class"); +} + +/* + * call-seq: + * Debugger.debug_load(file, stop = false, increment_start = false) -> nil + * + * Same as Kernel#load but resets current context's frames. + * +stop+ parameter forces the debugger to stop at the first line of code in the +file+ + * +increment_start+ determines if start_count should be incremented. When + * control threads are used, they have to be set up before loading the + * debugger; so here +increment_start+ will be false. + * FOR INTERNAL USE ONLY. + */ +static VALUE +debug_debug_load(int argc, VALUE *argv, VALUE self) +{ + VALUE file, stop, context, increment_start; + debug_context_t *debug_context; + int state = 0; + + if(rb_scan_args(argc, argv, "12", &file, &stop, &increment_start) == 1) + { + stop = Qfalse; + increment_start = Qtrue; + } + + debug_start(self); + if (Qfalse == increment_start) start_count--; + + context = debug_current_context(self); + Data_Get_Struct(context, debug_context_t, debug_context); + debug_context->stack_size = 0; + if(RTEST(stop)) + debug_context->stop_next = 1; + /* Initializing $0 to the script's path */ + ruby_script(RSTRING(file)->ptr); + rb_load_protect(file, 0, &state); + if (0 != state) { + VALUE errinfo = ruby_errinfo; + debug_suspend(self); + reset_stepping_stop_points(debug_context); + ruby_errinfo = Qnil; + return errinfo; + } + + /* We should run all at_exit handler's in order to provide, + * for instance, a chance to run all defined test cases */ + rb_exec_end_proc(); + + /* We could have issued a Debugger.stop inside the debug + session. */ + if (start_count > 0) { + debug_stop(self); + } + + return Qnil; +} + +static VALUE +set_current_skipped_status(VALUE status) +{ + VALUE context; + debug_context_t *debug_context; + + context = debug_current_context(Qnil); + Data_Get_Struct(context, debug_context_t, debug_context); + if(status) + CTX_FL_SET(debug_context, CTX_FL_SKIPPED); + else + CTX_FL_UNSET(debug_context, CTX_FL_SKIPPED); + return Qnil; +} + +/* + * call-seq: + * Debugger.skip { block } -> obj or nil + * + * The code inside of the block is escaped from the debugger. + */ +static VALUE +debug_skip(VALUE self) +{ + if (!rb_block_given_p()) { + rb_raise(rb_eArgError, "called without a block"); + } + if(!IS_STARTED) + return rb_yield(Qnil); + set_current_skipped_status(Qtrue); + return rb_ensure(rb_yield, Qnil, set_current_skipped_status, Qfalse); +} + +static VALUE +debug_at_exit_c(VALUE proc) +{ + return rb_funcall(proc, rb_intern("call"), 0); +} + +static void +debug_at_exit_i(VALUE proc) +{ + if(!IS_STARTED) + { + debug_at_exit_c(proc); + } + else + { + set_current_skipped_status(Qtrue); + rb_ensure(debug_at_exit_c, proc, set_current_skipped_status, Qfalse); + } +} + +/* + * call-seq: + * Debugger.debug_at_exit { block } -> proc + * + * Register at_exit hook which is escaped from the debugger. + * FOR INTERNAL USE ONLY. + */ +static VALUE +debug_at_exit(VALUE self) +{ + VALUE proc; + if (!rb_block_given_p()) + rb_raise(rb_eArgError, "called without a block"); + proc = rb_block_proc(); + rb_set_end_proc(debug_at_exit_i, proc); + return proc; +} + +/* + * call-seq: + * context.step(steps, force = false) + * + * Stops the current context after a number of +steps+ are made. + * +force+ parameter (if true) ensures that the cursor moves from the current line. + */ +static VALUE +context_stop_next(int argc, VALUE *argv, VALUE self) +{ + VALUE steps, force; + debug_context_t *debug_context; + + debug_check_started(); + + rb_scan_args(argc, argv, "11", &steps, &force); + if(FIX2INT(steps) < 0) + rb_raise(rb_eRuntimeError, "Steps argument can't be negative."); + + Data_Get_Struct(self, debug_context_t, debug_context); + debug_context->stop_next = FIX2INT(steps); + if(RTEST(force)) + CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE); + else + CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE); + + return steps; +} + +/* + * call-seq: + * context.step_over(steps, frame = nil, force = false) + * + * Steps over a +steps+ number of times. + * Make step over operation on +frame+, by default the current frame. + * +force+ parameter (if true) ensures that the cursor moves from the current line. + */ +static VALUE +context_step_over(int argc, VALUE *argv, VALUE self) +{ + VALUE lines, frame, force; + debug_context_t *debug_context; + + debug_check_started(); + Data_Get_Struct(self, debug_context_t, debug_context); + if(debug_context->stack_size == 0) + rb_raise(rb_eRuntimeError, "No frames collected."); + + rb_scan_args(argc, argv, "12", &lines, &frame, &force); + debug_context->stop_line = FIX2INT(lines); + CTX_FL_UNSET(debug_context, CTX_FL_STEPPED); + if(frame == Qnil) + { + debug_context->dest_frame = debug_context->stack_size; + } + else + { + if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size) + rb_raise(rb_eRuntimeError, "Destination frame is out of range."); + debug_context->dest_frame = debug_context->stack_size - FIX2INT(frame); + } + if(RTEST(force)) + CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE); + else + CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE); + + return Qnil; +} + +/* + * call-seq: + * context.stop_frame(frame) + * + * Stops when a frame with number +frame+ is activated. Implements +finish+ and +next+ commands. + */ +static VALUE +context_stop_frame(VALUE self, VALUE frame) +{ + debug_context_t *debug_context; + + debug_check_started(); + Data_Get_Struct(self, debug_context_t, debug_context); + if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size) + rb_raise(rb_eRuntimeError, "Stop frame is out of range."); + debug_context->stop_frame = debug_context->stack_size - FIX2INT(frame); + + return frame; +} + +inline static int +check_frame_number(debug_context_t *debug_context, VALUE frame) +{ + int frame_n; + + frame_n = FIX2INT(frame); + if(frame_n < 0 || frame_n >= debug_context->stack_size) + rb_raise(rb_eArgError, "Invalid frame number %d, stack (0...%d)", + frame_n, debug_context->stack_size); + return frame_n; +} + +static int +optional_frame_position(int argc, VALUE *argv) { + unsigned int i_scanned; + VALUE level; + + if ((argc > 1) || (argc < 0)) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc); + i_scanned = rb_scan_args(argc, argv, "01", &level); + if (0 == i_scanned) { + level = INT2FIX(0); + } + return level; +} + +/* + * call-seq: + * context.frame_args_info(frame_position=0) -> list + if track_frame_args or nil otherwise + * + * Returns info saved about call arguments (if any saved). + */ +static VALUE +context_frame_args_info(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + return RTEST(track_frame_args) ? GET_FRAME->arg_ary : Qnil; +} + +/* + * call-seq: + * context.frame_binding(frame_position=0) -> binding + * + * Returns frame's binding. + */ +static VALUE +context_frame_binding(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + return GET_FRAME->binding; +} + +/* + * call-seq: + * context.frame_method(frame_position=0) -> sym + * + * Returns the sym of the called method. + */ +static VALUE +context_frame_id(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + ID id; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + id = GET_FRAME->id; + return id ? ID2SYM(id): Qnil; +} + +/* + * call-seq: + * context.frame_line(frame_position) -> int + * + * Returns the line number in the file. + */ +static VALUE +context_frame_line(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + return INT2FIX(GET_FRAME->line); +} + +/* + * call-seq: + * context.frame_file(frame_position) -> string + * + * Returns the name of the file. + */ +static VALUE +context_frame_file(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + return rb_str_new2(GET_FRAME->file); +} + +static int +arg_value_is_small(VALUE val) +{ + switch (TYPE(val)) { + case T_FIXNUM: case T_FLOAT: case T_CLASS: + case T_NIL: case T_MODULE: case T_FILE: + case T_TRUE: case T_FALSE: case T_UNDEF: + return 1; + default: + return SYMBOL_P(val); + } +} + +/* + * Save scalar arguments or a class name. + */ +static void +copy_scalar_args(debug_frame_t *debug_frame) +{ + unsigned int i; + ID *tbl = ruby_scope->local_tbl;; + if (tbl && ruby_scope->local_vars) + { + int n = *tbl++; + if (debug_frame->argc+2 < n) n = debug_frame->argc+2; + debug_frame->arg_ary = rb_ary_new2(n); + for (i=2; iarg_ary, val); + else + rb_ary_push(debug_frame->arg_ary, + rb_str_new2(rb_obj_classname(val))); + } + } + } +} + + +/* + * call-seq: + * context.copy_args(frame) -> list of args + * + * Returns a array of argument names. + */ +static VALUE +context_copy_args(debug_frame_t *debug_frame) +{ + ID *tbl; + int n, i; + struct SCOPE *scope; + VALUE list = rb_ary_new2(0); /* [] */ + + scope = debug_frame->info.runtime.scope; + tbl = scope->local_tbl; + + if (tbl && scope->local_vars) + { + n = *tbl++; + if (debug_frame->argc+2 < n) n = debug_frame->argc+2; + list = rb_ary_new2(n); + /* skip first 2 ($_ and $~) */ + for (i=2; iinfo.runtime.scope; + tbl = scope->local_tbl; + + if (tbl && scope->local_vars) + { + n = *tbl++; + for (i=2; ilocal_vars[i]); + } + } + + vars = debug_frame->info.runtime.dyna_vars; + while (vars) + { + if (vars->id && rb_is_local_id(vars->id)) + { /* skip $_, $~ and flip states */ + rb_hash_aset(hash, rb_str_new2(rb_id2name(vars->id)), vars->val); + } + vars = vars->next; + } + return hash; +} + +/* + * call-seq: + * context.frame_locals(frame) -> hash + * + * Returns frame's local variables. + */ +static VALUE +context_frame_locals(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + debug_frame_t *debug_frame; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + debug_frame = GET_FRAME; + if(debug_frame->dead) + return debug_frame->info.copy.locals; + else + return context_copy_locals(debug_frame); +} + +/* + * call-seq: + * context.frame_args(frame_position=0) -> list + * + * Returns frame's argument parameters + */ +static VALUE +context_frame_args(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + debug_frame_t *debug_frame; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + debug_frame = GET_FRAME; + if(debug_frame->dead) + return debug_frame->info.copy.args; + else + return context_copy_args(debug_frame); +} + +/* + * call-seq: + * context.frame_self(frame_postion=0) -> obj + * + * Returns self object of the frame. + */ +static VALUE +context_frame_self(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + debug_frame_t *debug_frame; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + debug_frame = GET_FRAME; + return debug_frame->self; +} + +/* + * call-seq: + * context.frame_class(frame_position) -> obj + * + * Returns the real class of the frame. + * It could be different than context.frame_self(frame).class + */ +static VALUE +context_frame_class(int argc, VALUE *argv, VALUE self) +{ + VALUE frame; + debug_context_t *debug_context; + debug_frame_t *debug_frame; + VALUE klass; + + debug_check_started(); + frame = optional_frame_position(argc, argv); + Data_Get_Struct(self, debug_context_t, debug_context); + + debug_frame = GET_FRAME; + + if(CTX_FL_TEST(debug_context, CTX_FL_DEAD)) + return Qnil; + +#if RUBY_VERSION_CODE >= 190 + klass = debug_frame->info.runtime.frame->this_class; +#else + klass = debug_frame->info.runtime.frame->last_class; +#endif + + klass = real_class(klass); + if(TYPE(klass) == T_CLASS || TYPE(klass) == T_MODULE) + return klass; + return Qnil; +} + + +/* + * call-seq: + * context.stack_size-> int + * + * Returns the size of the context stack. + */ +static VALUE +context_stack_size(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + Data_Get_Struct(self, debug_context_t, debug_context); + + return INT2FIX(debug_context->stack_size); +} + +/* + * call-seq: + * context.thread -> thread + * + * Returns a thread this context is associated with. + */ +static VALUE +context_thread(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + Data_Get_Struct(self, debug_context_t, debug_context); + return context_thread_0(debug_context); +} + +/* + * call-seq: + * context.thnum -> int + * + * Returns the context's number. + */ +static VALUE +context_thnum(VALUE self) +{ + debug_context_t *debug_context; + + Data_Get_Struct(self, debug_context_t, debug_context); + return INT2FIX(debug_context->thnum); +} + +static void +context_suspend_0(debug_context_t *debug_context) +{ + VALUE status; + + status = rb_funcall(context_thread_0(debug_context), rb_intern("status"), 0); + if(rb_str_cmp(status, rb_str_new2("run")) == 0) + CTX_FL_SET(debug_context, CTX_FL_WAS_RUNNING); + else if(rb_str_cmp(status, rb_str_new2("sleep")) == 0) + CTX_FL_UNSET(debug_context, CTX_FL_WAS_RUNNING); + else + return; + CTX_FL_SET(debug_context, CTX_FL_SUSPEND); +} + +static void +context_resume_0(debug_context_t *debug_context) +{ + if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND)) + return; + CTX_FL_UNSET(debug_context, CTX_FL_SUSPEND); + if(CTX_FL_TEST(debug_context, CTX_FL_WAS_RUNNING)) + rb_thread_wakeup(context_thread_0(debug_context)); +} + +/* + * call-seq: + * context.suspend -> nil + * + * Suspends the thread when it is running. + */ +static VALUE +context_suspend(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND)) + rb_raise(rb_eRuntimeError, "Already suspended."); + context_suspend_0(debug_context); + return Qnil; +} + +/* + * call-seq: + * context.suspended? -> bool + * + * Returns +true+ if the thread is suspended by debugger. + */ +static VALUE +context_is_suspended(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return CTX_FL_TEST(debug_context, CTX_FL_SUSPEND) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * context.resume -> nil + * + * Resumes the thread from the suspended mode. + */ +static VALUE +context_resume(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND)) + rb_raise(rb_eRuntimeError, "Thread is not suspended."); + context_resume_0(debug_context); + return Qnil; +} + +/* + * call-seq: + * context.tracing -> bool + * + * Returns the tracing flag for the current context. + */ +static VALUE +context_tracing(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return CTX_FL_TEST(debug_context, CTX_FL_TRACING) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * context.tracing = bool + * + * Controls the tracing for this context. + */ +static VALUE +context_set_tracing(VALUE self, VALUE value) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + if(RTEST(value)) + CTX_FL_SET(debug_context, CTX_FL_TRACING); + else + CTX_FL_UNSET(debug_context, CTX_FL_TRACING); + return value; +} + +/* + * call-seq: + * context.ignored? -> bool + * + * Returns the ignore flag for the current context. + */ +static VALUE +context_ignored(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return CTX_FL_TEST(debug_context, CTX_FL_IGNORE) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * context.dead? -> bool + * + * Returns +true+ if context doesn't represent a live context and is created + * during post-mortem exception handling. + */ +static VALUE +context_dead(VALUE self) +{ + debug_context_t *debug_context; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + return CTX_FL_TEST(debug_context, CTX_FL_DEAD) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * context.stop_reason -> sym + * + * Returns the reason for the stop. It maybe of the following values: + * :initial, :step, :breakpoint, :catchpoint, :post-mortem + */ +static VALUE +context_stop_reason(VALUE self) +{ + debug_context_t *debug_context; + char * sym_name; + + debug_check_started(); + + Data_Get_Struct(self, debug_context_t, debug_context); + + switch(debug_context->stop_reason) + { + case CTX_STOP_STEP: + sym_name = "step"; + break; + case CTX_STOP_BREAKPOINT: + sym_name = "breakpoint"; + break; + case CTX_STOP_CATCHPOINT: + sym_name = "catchpoint"; + break; + case CTX_STOP_NONE: + default: + sym_name = "none"; + } + if(CTX_FL_TEST(debug_context, CTX_FL_DEAD)) + sym_name = "post-mortem"; + + return ID2SYM(rb_intern(sym_name)); +} + + +/* + * Document-class: Context + * + * == Summary + * + * Debugger keeps a single instance of this class for each Ruby thread. + */ +static void +Init_context() +{ + cContext = rb_define_class_under(mDebugger, "Context", rb_cObject); + rb_define_method(cContext, "stop_next=", context_stop_next, -1); + rb_define_method(cContext, "step", context_stop_next, -1); + rb_define_method(cContext, "step_over", context_step_over, -1); + rb_define_method(cContext, "stop_frame=", context_stop_frame, 1); + rb_define_method(cContext, "thread", context_thread, 0); + rb_define_method(cContext, "thnum", context_thnum, 0); + rb_define_method(cContext, "stop_reason", context_stop_reason, 0); + rb_define_method(cContext, "suspend", context_suspend, 0); + rb_define_method(cContext, "suspended?", context_is_suspended, 0); + rb_define_method(cContext, "resume", context_resume, 0); + rb_define_method(cContext, "tracing", context_tracing, 0); + rb_define_method(cContext, "tracing=", context_set_tracing, 1); + rb_define_method(cContext, "ignored?", context_ignored, 0); + rb_define_method(cContext, "frame_args", context_frame_args, -1); + rb_define_method(cContext, "frame_args_info", context_frame_args_info, -1); + rb_define_method(cContext, "frame_binding", context_frame_binding, -1); + rb_define_method(cContext, "frame_class", context_frame_class, -1); + rb_define_method(cContext, "frame_file", context_frame_file, -1); + rb_define_method(cContext, "frame_id", context_frame_id, -1); + rb_define_method(cContext, "frame_line", context_frame_line, -1); + rb_define_method(cContext, "frame_locals", context_frame_locals, -1); + rb_define_method(cContext, "frame_method", context_frame_id, -1); + rb_define_method(cContext, "frame_self", context_frame_self, -1); + rb_define_method(cContext, "stack_size", context_stack_size, 0); + rb_define_method(cContext, "dead?", context_dead, 0); + rb_define_method(cContext, "breakpoint", + context_breakpoint, 0); /* in breakpoint.c */ + rb_define_method(cContext, "set_breakpoint", + context_set_breakpoint, -1); /* in breakpoint.c */ +} + +/* + * call-seq: + * Debugger.breakpoints -> array + * + * Returns an array of breakpoints. + */ +static VALUE +debug_breakpoints(VALUE self) +{ + debug_check_started(); + + return rdebug_breakpoints; +} + +/* + * call-seq: + * Debugger.add_breakpoint(source, pos, condition = nil) -> breakpoint + * + * Adds a new breakpoint. + * source is a name of a file or a class. + * pos is a line number or a method name if source is a class name. + * condition is a string which is evaluated to +true+ when this breakpoint + * is activated. + */ +static VALUE +debug_add_breakpoint(int argc, VALUE *argv, VALUE self) +{ + VALUE result; + + debug_check_started(); + + result = create_breakpoint_from_args(argc, argv, ++bkp_count); + rb_ary_push(rdebug_breakpoints, result); + return result; +} + +/* + * Document-class: Debugger + * + * == Summary + * + * This is a singleton class allows controlling the debugger. Use it to start/stop debugger, + * set/remove breakpoints, etc. + */ +#if defined(_WIN32) +__declspec(dllexport) +#endif +void +Init_ruby_debug() +{ + mDebugger = rb_define_module("Debugger"); + rb_define_const(mDebugger, "VERSION", rb_str_new2(DEBUG_VERSION)); + rb_define_module_function(mDebugger, "start_", debug_start, 0); + rb_define_module_function(mDebugger, "stop", debug_stop, 0); + rb_define_module_function(mDebugger, "started?", debug_is_started, 0); + rb_define_module_function(mDebugger, "breakpoints", debug_breakpoints, 0); + rb_define_module_function(mDebugger, "add_breakpoint", debug_add_breakpoint, -1); + rb_define_module_function(mDebugger, "remove_breakpoint", + rdebug_remove_breakpoint, + 1); /* in breakpoint.c */ + rb_define_module_function(mDebugger, "add_catchpoint", + rdebug_add_catchpoint, 1); /* in breakpoint.c */ + rb_define_module_function(mDebugger, "catchpoints", + debug_catchpoints, 0); /* in breakpoint.c */ + rb_define_module_function(mDebugger, "last_context", debug_last_interrupted, 0); + rb_define_module_function(mDebugger, "contexts", debug_contexts, 0); + rb_define_module_function(mDebugger, "current_context", debug_current_context, 0); + rb_define_module_function(mDebugger, "thread_context", debug_thread_context, 1); + rb_define_module_function(mDebugger, "suspend", debug_suspend, 0); + rb_define_module_function(mDebugger, "resume", debug_resume, 0); + rb_define_module_function(mDebugger, "tracing", debug_tracing, 0); + rb_define_module_function(mDebugger, "tracing=", debug_set_tracing, 1); + rb_define_module_function(mDebugger, "debug_load", debug_debug_load, -1); + rb_define_module_function(mDebugger, "skip", debug_skip, 0); + rb_define_module_function(mDebugger, "debug_at_exit", debug_at_exit, 0); + rb_define_module_function(mDebugger, "post_mortem?", debug_post_mortem, 0); + rb_define_module_function(mDebugger, "post_mortem=", debug_set_post_mortem, 1); + rb_define_module_function(mDebugger, "keep_frame_binding?", + debug_keep_frame_binding, 0); + rb_define_module_function(mDebugger, "keep_frame_binding=", + debug_set_keep_frame_binding, 1); + rb_define_module_function(mDebugger, "track_frame_args?", + debug_track_frame_args, 0); + rb_define_module_function(mDebugger, "track_frame_args=", + debug_set_track_frame_args, 1); + rb_define_module_function(mDebugger, "debug", debug_debug, 0); + rb_define_module_function(mDebugger, "debug=", debug_set_debug, 1); + + cThreadsTable = rb_define_class_under(mDebugger, "ThreadsTable", rb_cObject); + + cDebugThread = rb_define_class_under(mDebugger, "DebugThread", rb_cThread); + rb_define_singleton_method(cDebugThread, "inherited", + debug_thread_inherited, 1); + + Init_context(); + Init_breakpoint(); + + idAtBreakpoint = rb_intern("at_breakpoint"); + idAtCatchpoint = rb_intern("at_catchpoint"); + idAtLine = rb_intern("at_line"); + idAtReturn = rb_intern("at_return"); + idAtTracing = rb_intern("at_tracing"); + idList = rb_intern("list"); + + rb_mObjectSpace = rb_const_get(rb_mKernel, rb_intern("ObjectSpace")); + + rb_global_variable(&last_context); + rb_global_variable(&last_thread); + rb_global_variable(&locker); + rb_global_variable(&rdebug_breakpoints); + rb_global_variable(&rdebug_catchpoints); + rb_global_variable(&rdebug_threads_tbl); +} diff --git a/ext/ruby_debug.h b/ext/ruby_debug.h new file mode 100644 index 0000000..04a8ae2 --- /dev/null +++ b/ext/ruby_debug.h @@ -0,0 +1,123 @@ +#include +/* Context info */ +enum ctx_stop_reason {CTX_STOP_NONE, CTX_STOP_STEP, CTX_STOP_BREAKPOINT, + CTX_STOP_CATCHPOINT}; + +/* Context flags */ +#define CTX_FL_SUSPEND (1<<1) +#define CTX_FL_TRACING (1<<2) +#define CTX_FL_SKIPPED (1<<3) +#define CTX_FL_IGNORE (1<<4) +#define CTX_FL_DEAD (1<<5) +#define CTX_FL_WAS_RUNNING (1<<6) +#define CTX_FL_ENABLE_BKPT (1<<7) +#define CTX_FL_STEPPED (1<<8) +#define CTX_FL_FORCE_MOVE (1<<9) + +#define CTX_FL_TEST(c,f) ((c)->flags & (f)) +#define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0) +#define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0) + +typedef struct { + int argc; /* Number of arguments a frame should have. */ + VALUE binding; + ID id; + ID orig_id; + int line; + const char * file; + short dead; + VALUE self; + VALUE arg_ary; + union { + struct { + struct FRAME *frame; + struct SCOPE *scope; + struct RVarmap *dyna_vars; + } runtime; + struct { + VALUE args; + VALUE locals; + VALUE arg_ary; + } copy; + } info; +} debug_frame_t; + +typedef struct { + VALUE thread_id; + int thnum; + int flags; + enum ctx_stop_reason stop_reason; + int stop_next; + int dest_frame; + int stop_line; + int stop_frame; + int stack_size; + int stack_len; + debug_frame_t *frames; + const char * last_file; + int last_line; + VALUE breakpoint; +} debug_context_t; + +/* variables in ruby_debug.c */ +extern VALUE mDebugger; +extern VALUE rdebug_breakpoints; +extern VALUE rdebug_catchpoints; +extern VALUE rdebug_threads_tbl; + +/* routines in ruby_debug.c */ +extern int filename_cmp(VALUE source, char *file); + +#define IS_STARTED (rdebug_threads_tbl != Qnil) +static inline void +debug_check_started() +{ + if(!IS_STARTED) + { + rb_raise(rb_eRuntimeError, "Debugger.start is not called yet."); + } +} + +static inline int +classname_cmp(VALUE name, VALUE klass) +{ + VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name; + return (klass != Qnil + && rb_str_cmp(class_name, rb_mod_name(klass)) == 0); +} + +/* Breakpoint information */ +enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE}; +enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD}; + +typedef struct { + int id; + enum bp_type type; + VALUE source; + union + { + int line; + ID mid; + } pos; + VALUE expr; + VALUE enabled; + int hit_count; + int hit_value; + enum hit_condition hit_condition; +} debug_breakpoint_t; + +/* routines in breakpoint.c */ +extern int check_breakpoint_expression(VALUE breakpoint, VALUE binding); +extern int check_breakpoint_hit_condition(VALUE breakpoint); +extern VALUE check_breakpoints_by_method(debug_context_t *debug_context, + VALUE klass, ID mid); +extern VALUE check_breakpoints_by_pos(debug_context_t *debug_context, + char *file, int line); +extern VALUE create_breakpoint_from_args(int argc, VALUE *argv, int id); +extern VALUE context_breakpoint(VALUE self); +extern VALUE context_set_breakpoint(int argc, VALUE *argv, VALUE self); +extern VALUE rdebug_add_catchpoint(VALUE self, VALUE value); +extern VALUE debug_catchpoints(VALUE self); +extern VALUE rdebug_remove_breakpoint(VALUE self, VALUE id_value); + +extern void Init_breakpoint(); diff --git a/ext/win32/.cvsignore b/ext/win32/.cvsignore new file mode 100644 index 0000000..3bc7dfb --- /dev/null +++ b/ext/win32/.cvsignore @@ -0,0 +1,3 @@ +*.o +*.so +Makefile diff --git a/ext/win32/.svn/README.txt b/ext/win32/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/ext/win32/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/ext/win32/.svn/dir-prop-base b/ext/win32/.svn/dir-prop-base new file mode 100644 index 0000000..abe19cc --- /dev/null +++ b/ext/win32/.svn/dir-prop-base @@ -0,0 +1,8 @@ +K 10 +svn:ignore +V 18 +*.o +*.so +Makefile + +END diff --git a/ext/win32/.svn/dir-props b/ext/win32/.svn/dir-props new file mode 100644 index 0000000..abe19cc --- /dev/null +++ b/ext/win32/.svn/dir-props @@ -0,0 +1,8 @@ +K 10 +svn:ignore +V 18 +*.o +*.so +Makefile + +END diff --git a/ext/win32/.svn/empty-file b/ext/win32/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/ext/win32/.svn/entries b/ext/win32/.svn/entries new file mode 100644 index 0000000..97a4026 --- /dev/null +++ b/ext/win32/.svn/entries @@ -0,0 +1,23 @@ + + + + + diff --git a/ext/win32/.svn/format b/ext/win32/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/ext/win32/.svn/format @@ -0,0 +1 @@ +4 diff --git a/ext/win32/.svn/prop-base/.cvsignore.svn-base b/ext/win32/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/win32/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/ext/win32/.svn/props/.cvsignore.svn-work b/ext/win32/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/ext/win32/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/ext/win32/.svn/text-base/.cvsignore.svn-base b/ext/win32/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..3bc7dfb --- /dev/null +++ b/ext/win32/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1,3 @@ +*.o +*.so +Makefile diff --git a/lib/.svn/README.txt b/lib/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/lib/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/lib/.svn/empty-file b/lib/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/lib/.svn/entries b/lib/.svn/entries new file mode 100644 index 0000000..e5122b0 --- /dev/null +++ b/lib/.svn/entries @@ -0,0 +1,31 @@ + + + + + + diff --git a/lib/.svn/format b/lib/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/lib/.svn/format @@ -0,0 +1 @@ +4 diff --git a/lib/.svn/prop-base/ChangeLog.svn-base b/lib/.svn/prop-base/ChangeLog.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/lib/.svn/prop-base/ChangeLog.svn-base @@ -0,0 +1 @@ +END diff --git a/lib/.svn/prop-base/ruby-debug-base.rb.svn-base b/lib/.svn/prop-base/ruby-debug-base.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/lib/.svn/prop-base/ruby-debug-base.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/lib/.svn/props/ChangeLog.svn-work b/lib/.svn/props/ChangeLog.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/lib/.svn/props/ChangeLog.svn-work @@ -0,0 +1 @@ +END diff --git a/lib/.svn/props/ruby-debug-base.rb.svn-work b/lib/.svn/props/ruby-debug-base.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/lib/.svn/props/ruby-debug-base.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/lib/.svn/text-base/ChangeLog.svn-base b/lib/.svn/text-base/ChangeLog.svn-base new file mode 100644 index 0000000..12c8f69 --- /dev/null +++ b/lib/.svn/text-base/ChangeLog.svn-base @@ -0,0 +1,1065 @@ +2009-03-29 03:00 Rocky Bernstein + + * ChangeLog: Canonicalize breakpoint locations a little better. + More work should be done and more work should be done on the + testing side too. + +2009-03-11 23:42 Rocky Bernstein + + * ChangeLog: update texinfo for catch + +2008-11-25 02:43 Rocky Bernstein + + * ChangeLog: Frame without a frame number means frame 0, same as + gdb. We are now in 0.10.4 territory now. + +2008-11-16 00:14 Rocky Bernstein + + * ChangeLog: Add rdoc for rdebug script. + +2008-11-14 19:28 Rocky Bernstein + + * ruby-debug-base.rb: Go over documentation and revise. + +2008-11-14 15:32 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Move Debugger#debugger from base + to cli. Revert code in ruby_debug.c and block parameter in + debugger. cf. -> Compare with. Document Debugger.start better. + +2008-11-13 10:29 Rocky Bernstein + + * ChangeLog: Make Debugger.start{block} work if Debugger.started? + is false. Second try. + +2008-11-11 02:07 Rocky Bernstein + + * ChangeLog: Tweak truncated stack test since Ruby's caller doesn't + seem to include (tail?) recursive calls and we do. Get regression + tests working in light of recent changes. + +2008-11-10 01:48 Kent Sibilev + + * ruby-debug-base.rb: a little bit more readable + +2008-11-10 01:35 Kent Sibilev + + * ruby-debug-base.rb: Debugger.start must always call the passed + block + +2008-11-07 19:35 Rocky Bernstein + + * ChangeLog: Change truncated frame message. + +2008-11-07 10:39 Rocky Bernstein + + * ChangeLog: Add check to "where" to see if the call stack is + truncated; task #2354 + +2008-11-06 16:17 Rocky Bernstein + + * ChangeLog: #22698 Allow ruby-debug-base 0.x.y.z be compatible + with ruby-debug 0.x.y. + +2008-11-02 21:59 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Debugger.start with a block now + stops inside the block. Debugger.debugger with a block works like + Debugger.start with a block. + + The whole interface is hopelessly kludgy and needs to be redone. + +2008-10-26 14:54 Rocky Bernstein + + * ChangeLog: Doc typo. Add comment to remind me how to turn off + optimizationin extconf.rb + +2008-10-25 16:01 Rocky Bernstein + + * ChangeLog: Warn and add a "confirmation" when setting a + breakpoint on a file that is not loaded. Regression tests no + longer fail. + +2008-09-22 00:07 Rocky Bernstein + + * ruby-debug-base.rb: #22118 bug in showing variables post mortem. + Patch thanks to rubikitch. + Update pm.rb integration test. + +2008-09-03 17:29 Rocky Bernstein + + * ChangeLog: Show line numbers when $DEBUG is set. Patch #21772 + from Martin Krauskopf + +2008-07-07 07:11 Rocky Bernstein + + * ruby-debug-base.rb: Tracker [#20041] start erroneously moved to + Kernel - should be in + Debugger.start + +2008-06-20 06:46 Rocky Bernstein + + * ruby-debug-base.rb: trace.rb: add "trace var" + ruby-debug-base.rb: remove another undefined warning. + +2008-05-24 01:27 Rocky Bernstein + + * ChangeLog: Remove dup lines. + +2008-05-15 16:05 Rocky Bernstein + + * ChangeLog: Handle "catch nnn off" Forgotten there during r656. + From mkrauskopf [#20156]. + +2008-05-05 18:05 Rocky Bernstein + + * ChangeLog: make test-frame installation independent. Bug #19931 + +2008-04-29 13:37 Rocky Bernstein + + * ChangeLog: Test line number in "continue" command for validity. + +2008-04-28 16:16 Rocky Bernstein + + * ChangeLog: From Martin Krauskopf via patch #19779 + + Allow folks to configure Ruby used for CLI tests in the + test/config.yaml. The defaults are for native Ruby, so nothing + needs + to be done for ruby-debug. + + Developers of interfaces other than cli might override + config.yaml by + customized config.private.yaml which is ignored. So there will be + no + trash in e.g. 'svn st' output when developer customize the Ruby + to be + used. + + Handy for alternative interface implementations using + svn:externals. + +2008-04-22 02:49 Rocky Bernstein + + * ruby-debug-base.rb: Experiment with debugger(steps=0). Puts us in + the debugger call, but this may be the best we can do for now. + See tracker + #19639. + +2008-04-16 01:11 Rocky Bernstein + + * ChangeLog: In 0.10.2 now. Some work to cope systems without + readline. More work is needed. + Add test of "set autoeval." Undefined command message more + closely like gdb's. + +2008-04-10 08:49 Rocky Bernstein + + * ChangeLog: linecache is required by ruby-debug-base not + ruby-debug. Thanks Martin! + +2008-04-10 08:00 Rocky Bernstein + + * ChangeLog: Last change before 0.10.1 release. + +2008-04-10 02:03 Rocky Bernstein + + * ChangeLog: Cosmetic stuff: spelling corrections. Update node + structure so texinfo + doesn't complain. + +2008-04-08 14:52 Rocky Bernstein + + * ChangeLog: autorequire is deprecated and presumably no longer + needed + http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/182827 + +2008-04-07 00:36 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: ruby-debug-base.rb: document + Debugger.start parameters. + CHANGES: Revise what's happened + test-shortkey.el: A failing regression test because I think + rdebug-shortkey-mode + is not correct. + +2008-04-03 19:01 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Allow setting :post_mortem => true + from Debugger.start. + +2008-03-28 13:53 Rocky Bernstein + + * ChangeLog: Don't unconditionally turn on short-key mode when + annotations are on. Use rdebug-short-key-mode setting to decide. + +2008-03-23 17:47 Rocky Bernstein + + * ChangeLog: set.rb -> settings.rb since it's already one command + per file, and + remove another :nodoc. + Rakefile: split long line + +2008-03-18 16:05 Rocky Bernstein + + * ChangeLog: Fix bug in 'list' command when wrapping off the end. + test-finish.rb: tolerate buggy in Ruby versions <= 1.8.7. + +2008-03-13 02:15 Rocky Bernstein + + * ruby-debug-base.rb: INCOMPATIBLE CHANGE: "finish" works like gdb + - stop just before the + most recent method finishes. Will now accept a number which stops + that + many frames completed. (Note that return line numbers will be + funny, + the first line of the method until Ruby 1.8.7.) + +2008-03-10 13:28 Rocky Bernstein + + * ChangeLog: Dunno why we are now one line number less. So be it + (for now). + +2008-03-09 23:30 Rocky Bernstein + + * ChangeLog: For now we require the duplicate numbers on + conditionals. + +2008-03-02 04:20 Rocky Bernstein + + * ruby-debug-base.rb: Better error message for an invalid break + command. + +2008-02-28 05:06 Rocky Bernstein + + * ChangeLog: breakpoints.{cmd,right}: test for an invalid stopping + line number + rdebug-fns.el: move generic split-string-and-unquote from + rdebug-core. + rdebug-core.el: Add rdebug-common-init to replace + gud-common-init. Is + simpler, and finds files better via debugger output/annotations. + Fix bug in rdebug-setup-windows: gud-find-file can return nil, + and + we still need to set buf. + +2008-02-27 04:04 Rocky Bernstein + + * ruby-debug-base.rb: Slightly more robust handle_post_mortem. + +2008-02-26 17:31 Rocky Bernstein + + * ChangeLog: Go over source location positioning. 0 is now the + oldest (first) position. Add M-S-down and M-S-up for first and + last. More tests needed in test-fns.el and need to prompt on wrap + around. + +2008-02-26 00:57 Rocky Bernstein + + * ChangeLog: Fix bug in "info file xxx breakpoints". + +2008-02-24 16:36 Rocky Bernstein + + * ChangeLog: rdebug; make more Ruby 1.9 compatible. + +2008-02-24 16:14 Rocky Bernstein + + * ChangeLog: Minor changes. + rdbg.rb: don't need $DEBUG test any more + rdebug-regexp.el: go over with checkdoc + bin/rdebug: use PATH_SEPARATOR (for 'doze again) + +2008-02-24 04:51 Rocky Bernstein + + * ChangeLog: CLI: Add long help for "info file". + + test/test-help.rb: Make test failures easier to fix and more like + the + other tests. + + emacs/test: finish testing all of the funcitons in rdebug-fns.el + + rdebug-layouts.el: Make checkdoc clean. + rdebug-track.el: don't need to rename shell buffer. Do it as an + option only. + rdebug-secondary.el: get rid of hoaky buffer finding for at least + gud-comint-buf. (Should probably do others as well) + + DOC: Note weird line stopping locations. Describe what "ctrl" in + prompt means. + +2008-02-21 02:56 Rocky Bernstein + + * ChangeLog: Fringe for frame buffer the same as in source code. + Move + miscellaneous small functions to a new file. Reduce duplication + of + "chomp" code. + +2008-02-19 23:44 Rocky Bernstein + + * ChangeLog: rdebug-cmd.el: M-insert toggles shortkey mode in the + command buffer + rdebug: search for Ruby program if file is not found and no + SEPARATOR + chars in the filename + +2008-02-18 19:56 Rocky Bernstein + + * ChangeLog: Frame switching shouldn't be recorded in position + history ring. + +2008-02-17 13:57 Rocky Bernstein + + * ruby-debug-base.rb: Add Debugger.last_exception. Show exception + in post-mortem when "info program" + is issued. Reorganize list of major changes better. + +2008-02-13 21:47 Rocky Bernstein + + * ChangeLog: processor.rb: spelled "post-mortem" incorrectly in + prompt. + +2008-02-13 17:32 Rocky Bernstein + + * ChangeLog: Set up keys for comint-next-prompt and + comint-previous-prompt. + +2008-02-12 02:06 Rocky Bernstein + + * ChangeLog: Fix bug in "info thread verbose" which wasn't showing + full traceback. + +2008-02-09 15:48 Rocky Bernstein + + * ChangeLog: helper.rb Failed attempt to DRY tests more. But save + what we have + which may someday in the future be used to go further. Minus to + undercore in Data file names in preparation such time. (We'll use + the + filename as the test name). + + testing + +2008-02-06 16:15 Rocky Bernstein + + * ChangeLog: Add 'nowarn to find-file-noselect and test that we + don't get a warning. + +2008-02-05 01:41 Rocky Bernstein + + * ChangeLog: rdebug.el: Add a defgroup for rdebug so customization + in Emacs 23 is possible. + Some other minor doc fixes. + setshow.* make sure we don't have an $Id line that we have to + check against. + +2008-02-03 15:23 Rocky Bernstein + + * ChangeLog: Try to get testing a little more organized, although + more work should + be done: Create a data directory for comparison ("right") and + script + command ("cmd") files. Code is now more uniform (and should DRY'd + a + bit more). + +2008-02-02 23:10 Rocky Bernstein + + * ChangeLog: Remove commands in post-mortem which are not + applicable, e.g."step", + "next", "continue"... + + "No breakpoints have been set" is now an error message when + trying to + set a breakpoint. + + Add post-mortem test. + + Debug.init no longer exists. + +2008-02-02 09:27 Rocky Bernstein + + * ruby-debug-base.rb: Remove Debugger.init and fold options + parameter into Debugger.start. + Old Debugger.start has been renamed Deebugger.start_ + +2008-01-31 16:30 Rocky Bernstein + + * ChangeLog: Leave ruby_debug.c this way for now. + +2008-01-31 16:24 Rocky Bernstein + + * ChangeLog: ruby_debug.c: more adventures in exception handling + processor.rb: Removal of crash when annotate is on. Need to fix + the source of the + problem though. + +2008-01-31 15:16 Rocky Bernstein + + * ruby-debug-base.rb: Handle post-mortem and exception traceback + reporting in ruby-debug + +2008-01-30 17:01 Rocky Bernstein + + * ChangeLog: Add Command.find() to find a subcommand name. + condition.right: correct for breakpoint hit counts. + +2008-01-30 01:43 Rocky Bernstein + + * ChangeLog: Add number of times a breakpoint is hit like gdb does. + +2008-01-29 22:37 Rocky Bernstein + + * ChangeLog: Columnize breakpoint output. + +2008-01-29 11:20 Rocky Bernstein + + * ChangeLog: More annotate=2 fixes. + +2008-01-28 15:59 Rocky Bernstein + + * ChangeLog: Add info file breakpoints to show lines which we can + set a breakpoint on. + Revise so we chdir into SRC_DIR. + test-hist.rb is broken - will fix later. + +2008-01-25 12:11 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Add Debugger.init which intializes + things that rdebug does. This + allows a restart even though rdebug wasn't called initially. + +2008-01-22 23:15 Rocky Bernstein + + * ChangeLog: Allow "help info xxx". Add ability for long help on + "info" command. + Add "info break xx". + + test: remove test/unit class name conflicts. All the tests we + wrote + now get run. + +2008-01-19 19:28 Rocky Bernstein + + * ChangeLog: Move ruby-debug-base tests to base directory. Add a + binding_n regression test. + +2008-01-16 18:42 Rocky Bernstein + + * ChangeLog: Need to present source filename (__FILE__) as Ruby and + therefore breakpoint + sees it. + + +2008-01-16 02:19 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Line caching moved to an external + gem, linecache. We now require + version 0.2 of that or greater. + +2008-01-14 01:31 Rocky Bernstein + + * ChangeLog: Make rdebug-track work better in the face of prompt + and error annotations. + control.rb: need another test when rdebug not called initially. + +2008-01-13 21:51 Rocky Bernstein + + * ChangeLog: Some stack -> frame renaming + ext/breakpoint.c: put methods in alpha order (to help with + reference man) + breakpoints.rb: one print -> errmsg + +2008-01-13 18:13 Rocky Bernstein + + * ChangeLog: Create errmsg routine for error output, start tagging + error messages + as errors. Under annotate 3, output errors similar to gdb + --annotate + does (although still simplified). Have Emacs pick up debugger + error + annotations. + +2008-01-13 04:05 Rocky Bernstein + + * ChangeLog: Check validity of expressions in breakpoint conditions + and don't allow + enabling a syntactically invalid expression. + + Start noting messages which are errors via an errmsg routine. + +2008-01-11 10:26 Rocky Bernstein + + * ChangeLog: Document that ruby-debug resets $0. Align program + options in ref manual and --help. Alphabetize better. + +2008-01-10 22:56 Rocky Bernstein + + * ChangeLog: More correct $0 fix. Deal with the case ./ is + automatically added. + However this might not be right in all cases. + +2008-01-10 22:25 Rocky Bernstein + + * ChangeLog: Was gobbling arg in processing --emacs. Add test. + +2008-01-10 10:34 Rocky Bernstein + + * ChangeLog: Add condition command. + +2008-01-09 19:10 Rocky Bernstein + + * ChangeLog: Rakefile: rdebug.rb -> rdbg.el + rdebug-dbg.el: Add $Id$ + +2008-01-09 19:03 Rocky Bernstein + + * ChangeLog: Break out secondary buffer into their own file, and + also internal + debug code and general secondary commands. Secondary buffer code + removed from rdebug-cmd and moved into the appropriate file. + + rdebug-edit-variables-value is not defined so comment out for + now. + +2008-01-08 16:04 Rocky Bernstein + + * ChangeLog: Restore $: to the value it was before rdebug call. + +2008-01-07 20:38 Rocky Bernstein + + * ChangeLog: Add "var class". This means "var const .." can no + longer be abbreviated "var c"; use "var co" instead. + (Or "var const" or "var constant" + +2008-01-07 19:57 Rocky Bernstein + + * ChangeLog: Add class level variables to "info variables" + +2008-01-07 17:37 Rocky Bernstein + + * ChangeLog: Add "self" to list "info variables" spits out. + +2008-01-07 09:59 Rocky Bernstein + + * ChangeLog: --emacs sets width to 120. rdebug-core.el will reset + to 120 unless it's already that. + +2008-01-07 04:29 Rocky Bernstein + + * ChangeLog: Split out ChangeLogs better (I hope). + +2008-01-06 20:56 Rocky Bernstein + + * ChangeLog: test/*-emacs-basic*, tdebug: Add test of running in + Emacs without annotations. + + emacs/*.el: make regexp tests work again, move regexp to from + core to regexp. + Add an annotate regexp test. + + processor.rb: Remove some anotation print from bleeding into + output + when annotations are not wanted. Reinstate "Program finished" in + annotations and outside (rdebug). + +2008-01-06 18:55 Rocky Bernstein + + * ChangeLog: Create Processor class and subclass that. Perhaps a + mixin would be good. + Remove annotation output bleanding when annotate is off. + Try to reduce the mess annotations is adding to processor.rb + rdebug-core.el: fix indentation to pass the regression test + Anders added + Makefile.am: Add rdebug-source.el to distribution. + Make sure "rake test" + +2008-01-06 02:15 Rocky Bernstein + + * ChangeLog: Some work on saving state across a restart. More work + is needed on the + script command to get this working. The save-file name is now + optional. save.rb split off from script.rb Display expressions + and + some settings are now captured in the save/restore file. + Add interface.finalize - things that need to be done before quit + or + restart. + +2008-01-05 21:16 Rocky Bernstein + + * ChangeLog: More work to make annotate more like gdb's. + starting/stopping/exiting + should be more similar. Some code has been commented out until we + get + the Emacs interface to match. See "FIXME: ANNOTATE" in + processor.rb. + Also regression tests for output and annotate currently fail for + this + reason. + +2008-01-02 20:35 Rocky Bernstein + + * ChangeLog: helper.rb: add regexp for a position. TODO: add + parsing routine and use in + various commands + +2008-01-02 14:41 Rocky Bernstein + + * ChangeLog: processor.rb: Redo where starting/exiting annotations + are done. + rdebug.el: back off on setting output command for now. + +2008-01-01 15:23 Rocky Bernstein + + * ChangeLog: Fix --emacs to do --no-quit properly. + +2008-01-01 09:00 Rocky Bernstein + + * ChangeLog: Remove RDoc warnings caused because C files have been + split up. + +2008-01-01 05:51 Rocky Bernstein + + * ChangeLog: reindent -> indent. Makefile.am: wasn't including all + test files. + +2007-12-31 06:26 Rocky Bernstein + + * ChangeLog: Rakefile: add spit-off C files to ruby-debug-base gem. + +2007-12-31 06:23 Rocky Bernstein + + * ChangeLog: rdebug-test-cmd.el: Indentation + +2007-12-31 06:08 Rocky Bernstein + + * ChangeLog: Changes and more changes. + +2007-12-29 13:31 Rocky Bernstein + + * ChangeLog: Remove looping on quit. "-n" is broken so remove it + for now. + +2007-12-28 15:33 Rocky Bernstein + + * ChangeLog: info.rb: Incorrect test for no display expressions. + display.rb: Grammar thing. + processor.rb: Slightly cleaner code + test/* more/better tests. + +2007-12-27 21:03 Rocky Bernstein + + * ChangeLog: Be more agressive about resetting gud-last-frame and + gud-last-last-frame. These foul up tracking when debugging is + interrupted. + We probably need a special "reset" command. + +2007-12-26 18:35 Rocky Bernstein + + * ChangeLog: Version number games - maybe 0.10.1 is better. + +2007-12-25 23:40 Rocky Bernstein + + * ChangeLog: Add step- and step+. Document as well as the new + toggle command. + +2007-12-25 09:55 Rocky Bernstein + + * ChangeLog: Small doc fixes. + +2007-12-25 07:51 Rocky Bernstein + + * ChangeLog: Last commit before 0.10.0 release. + +2007-12-25 02:51 Rocky Bernstein + + * ChangeLog: breakpoints.*: main -> Object. Add bad Class name test + AUTHOR: Add Anders + README: note ruby-debug-extra. More precise (I think) + +2007-12-24 00:25 Rocky Bernstein + + * ChangeLog: Rakefile: set up gem unit test for ruby-debug-base. + Add file in test/ + so we could do the same for ruby-debug were it not for other + mysterious + problems. + +2007-12-23 17:33 Rocky Bernstein + + * ChangeLog: Go over packaging: + ChangeLogs for ruby-debug-base (in ext and lib) separate from CLI + ChangeLog + ChangeLogs now map userid to names + ruby-debug-base regression test included in ruby-debug-base + Columnize test separated. (It will disappear when ruby-debug + requires it + as an external) + +2007-12-16 21:31 Rocky Bernstein + + * ruby-debug-base.rb: Add "info variables test". + + ruby-debug-base.rb: Not sure how test(?M, file) ever worked + before but change + to use File.stat(file).mtime + info.rb: ignore debugger variables which are sometimes set. + +2007-12-10 03:23 Rocky Bernstein + + * ruby-debug-base.rb: doc changes. + +2007-06-26 07:05 Rocky Bernstein + + * ruby-debug-base.rb: Run .rdebugrc on Debugger.start. Look for + this in the current directory and run that instead the one in + $HOME if that exists. Again, inspired and compatible with gdb. + + rdebug: Check script for syntax errors before loading. We get + more informative errors and it doesn't look like rdebug is at + fault. + +2007-06-05 16:36 Kent Sibilev + + * ruby-debug-base.rb: code reorganization. + reverted 'run' command. + +2007-06-05 07:59 Kent Sibilev + + * ruby-debug-base.rb: restore post_mortem + +2007-06-02 15:01 Rocky Bernstein + + * ruby-debug-base.rb: lib/ruby-debug-base.rb: add Quit and Restart + exceptions which can reliably be used after the delayed exception + handling bug is fixed + emacs/rdebug-track.el and cli/ruby-debug/processor.rb: more + accurate line tracking in EMACS. When not in emacs should be more + like what was there. + +2007-06-01 21:57 Rocky Bernstein + + * ruby-debug-base.rb: parens around a print seems to give a + warning. Remove. + +2007-05-23 16:43 Rocky Bernstein + + * ruby-debug-base.rb: post_mortem: to test $! *before* running + debug_at_ext or else we may get an erroneous message: + ruby-debug-base.rb:162:in `current_context': Debugger.start is + not called yet. (RuntimeError) + + A simple test case to show the problem: + + "require rubygems" + "require ruby-debug" + Debugger.start + Debugger.post_mortem + exit # Causes us to incorrectly give the above error + +2007-05-15 20:22 Kent Sibilev + + * ruby-debug-base.rb: various fixes + +2007-04-27 23:21 Kent Sibilev + + * ruby-debug-base.rb: ditto + +2007-04-27 23:19 Kent Sibilev + + * ruby-debug-base.rb: add breakpoint method as an alias for + debugger in case breakpoint method is not defined already + +2007-03-25 01:03 Kent Sibilev + + * ruby-debug-base.rb: will start the debugger if necessary + +2007-03-24 18:17 Kent Sibilev + + * stable becomes the trunk + +2007-03-13 17:06 Kent Sibilev + + * fixed rdoc + +2007-03-01 23:44 Kent Sibilev + + * fixed post-mortem + +2007-02-27 08:02 Kent Sibilev + + * repackaging ruby-debug + +2007-02-23 20:56 Kent Sibilev + + * added an option for Debugger.debug_load to stop at the first line + of code + +2007-02-12 06:59 Kent Sibilev + + * added --emacs option + +2007-02-09 16:56 Kent Sibilev + + * in remote mode the debugger shouldn't stop inside of rdebug + script + +2007-02-09 06:20 Kent Sibilev + + * -- + +2007-02-09 01:00 Kent Sibilev + + * fixed code reloading + made 'reload on' as a part of the 'set' command + evaluate ~/.rdebugrc as an init script + +2007-02-07 02:42 Kent Sibilev + + * should use ignored? method to check for the debugger's thread + +2007-02-06 22:21 Kent Sibilev + + * + +2007-02-05 22:48 Kent Sibilev + + * -- + +2007-02-05 22:11 Kent Sibilev + + * fixed emacs integration + +2007-02-05 20:16 Kent Sibilev + + * fixed another issue where a bogus frame is being left in the + stack + +2007-02-04 23:36 Kent Sibilev + + * seg fault bugfixes + fixed suspend/resume + +2007-02-04 03:49 Kent Sibilev + + * A better fix for the segmentation fault + +2007-02-03 20:24 Kent Sibilev + + * fix seg fault by avoiding ruby's bug + fixed Context#resume + when handling post-mortem all threads must be suspended + +2007-02-02 18:47 Kent Sibilev + + * removed ambiguity with down command + +2007-02-01 23:48 Kent Sibilev + + * typo + +2007-02-01 22:15 Kent Sibilev + + * made eval command available from the control thread + +2007-02-01 07:22 Kent Sibilev + + * added setting command + added Context#suspended? method + dispay suspended status in the thread list + display frame starting from zero + +2007-01-31 21:13 Kent Sibilev + + * ditto + +2007-01-31 21:12 Kent Sibilev + + * fixed help command + +2007-01-31 19:39 Kent Sibilev + + * fixed frame count + added frame_self method to context + +2007-01-31 16:48 Kent Sibilev + + * removed all references to frames array + fixed post-mortem debugging + +2007-01-31 00:51 Kent Sibilev + + * removed obsolete frames usage + +2007-01-31 00:41 Kent Sibilev + + * refactored out frame class and preallocate stack + made local variable available even when bindings are not + collected. + +2007-01-28 20:25 Kent Sibilev + + * -- + +2007-01-28 06:22 Kent Sibilev + + * - Control thread is always started by rdebug script. + - Ability to specify negative frame number to frame commands. + Patch from R. Bernstein. + +2007-01-28 04:52 Kent Sibilev + + * added top frame caching + control thread is always started by rdebug script + +2007-01-27 01:43 Kent Sibilev + + * another performance optimization + +2007-01-26 20:28 Kent Sibilev + + * fixed #7484 + +2007-01-26 17:59 Kent Sibilev + + * revisited file name comparing procedure + +2007-01-26 09:03 Kent Sibilev + + * performance improvements + +2007-01-26 03:12 Kent Sibilev + + * added option to exclude collecting of frame bindings + +2007-01-24 18:33 Kent Sibilev + + * disable tracing when in post-mortem + added -x/--trace option to rdebug script + +2007-01-21 08:13 Kent Sibilev + + * + +2007-01-21 03:34 Kent Sibilev + + * assign an id to the breakpoint + +2007-01-21 01:20 Kent Sibilev + + * added post_mortem_method wrap method + +2006-12-21 20:16 Kent Sibilev + + * added 'restart' command + +2006-12-21 14:12 Kent Sibilev + + * made 'exit' an alias to 'quit' + fixed the interoperability problem with rspec + +2006-12-21 13:43 Kent Sibilev + + * fixed trace command in post-mortem mode + +2006-12-21 01:59 Kent Sibilev + + * initialize only once + +2006-12-21 01:08 Kent Sibilev + + * fixes irb help command + +2006-12-20 21:19 Kent Sibilev + + * check that debugger has been started + +2006-12-20 20:08 Kent Sibilev + + * added post-mortem option to rdebug + +2006-12-20 19:38 Kent Sibilev + + * initial support for post-mortem debugging + +2006-12-19 06:13 Kent Sibilev + + * removed 'run' alias + +2006-12-18 08:34 Kent Sibilev + + * added irb command + fixed source_for method + +2006-12-02 19:15 Kent Sibilev + + * added reload command + +2006-12-02 18:32 Kent Sibilev + + * fixed #6518 and #6545 + +2006-12-01 06:47 Kent Sibilev + + * + +2006-11-21 23:29 Kent Sibilev + + * ensure that on/off is the last on the line + +2006-11-16 00:04 Kent Sibilev + + * fixed debug_method for assignment methods + +2006-11-16 00:01 Kent Sibilev + + * added the new branch for the stable version + +2006-10-15 22:43 Kent Sibilev + + * branching a stable version + +2006-10-15 22:26 Kent Sibilev + + * ruby-debug.rb: remove unused require + uploaded new windows binary + +2006-10-15 19:02 Kent Sibilev + + * ruby-debug/commands/display.rb: remove unused constructor + +2006-10-15 16:54 Kent Sibilev + + * ruby-debug.rb, ruby-debug/commands/threads.rb: new logic of + context suspend/resume + +2006-10-15 07:36 Kent Sibilev + + * ruby-debug.rb, ruby-debug/lock.rb: fixed locking of debugger + threads + +2006-10-09 22:01 Kent Sibilev + + * ruby-debug/interface.rb: fixes for windows version + +2006-10-09 19:06 Kent Sibilev + + * ruby-debug.rb, ruby-debug/interface.rb: added Debugger.skip and + Debugger.debug_at_exit methods + +2006-10-09 16:44 Kent Sibilev + + * ., ruby-debug, ruby-debug.rb, ruby-debug/command.rb, + ruby-debug/commands, ruby-debug/commands/breakpoints.rb, + ruby-debug/commands/catchpoint.rb, + ruby-debug/commands/control.rb, ruby-debug/commands/display.rb, + ruby-debug/commands/eval.rb, ruby-debug/commands/frame.rb, + ruby-debug/commands/help.rb, ruby-debug/commands/list.rb, + ruby-debug/commands/method.rb, ruby-debug/commands/script.rb, + ruby-debug/commands/stepping.rb, ruby-debug/commands/threads.rb, + ruby-debug/commands/tmate.rb, ruby-debug/commands/trace.rb, + ruby-debug/commands/variables.rb, ruby-debug/interface.rb, + ruby-debug/lock.rb, ruby-debug/processor.rb: initial import + diff --git a/lib/.svn/text-base/ruby-debug-base.rb.svn-base b/lib/.svn/text-base/ruby-debug-base.rb.svn-base new file mode 100644 index 0000000..5995a66 --- /dev/null +++ b/lib/.svn/text-base/ruby-debug-base.rb.svn-base @@ -0,0 +1,298 @@ +require 'ruby_debug.so' +require 'rubygems' +require 'linecache' + +module Debugger + + # Default options to Debugger.start + DEFAULT_START_SETTINGS = { + :init => true, # Set $0 and save ARGV? + :post_mortem => false, # post-mortem debugging on uncaught exception? + :tracing => nil # Debugger.tracing value. true/false resets, + # nil keeps the prior value + } unless defined?(DEFAULT_START_SETTINGS) + + class Context + def interrupt + self.stop_next = 1 + end + + alias __c_frame_binding frame_binding + def frame_binding(frame) + __c_frame_binding(frame) || hbinding(frame) + end + + private + + def hbinding(frame) + hash = frame_locals(frame) + code = hash.keys.map{|k| "#{k} = hash['#{k}']" unless k=='self' }.compact.join(';') + ';binding' + if obj = frame_self(frame) + obj.instance_eval code + else + eval code, TOPLEVEL_BINDING + end + end + + def handler + Debugger.handler or raise 'No interface loaded' + end + + def at_breakpoint(breakpoint) + handler.at_breakpoint(self, breakpoint) + end + + def at_catchpoint(excpt) + handler.at_catchpoint(self, excpt) + end + + def at_tracing(file, line) + handler.at_tracing(self, file, line) + end + + def at_line(file, line) + handler.at_line(self, file, line) + end + + def at_return(file, line) + handler.at_return(self, file, line) + end + end + + @reload_source_on_change = false + + class << self + # interface modules provide +handler+ object + attr_accessor :handler + + # if true, checks the modification time of source files and reloads if it was modified + attr_accessor :reload_source_on_change + + attr_accessor :last_exception + Debugger.last_exception = nil + + # + # Interrupts the current thread + # + def interrupt + current_context.interrupt + end + + # + # Interrupts the last debugged thread + # + def interrupt_last + if context = last_context + return nil unless context.thread.alive? + context.interrupt + end + context + end + + def source_reload + LineCache::clear_file_cache(true) + end + + # Get line +line_number+ from file named +filename+. Return "\n" + # there was a problem. Leaking blanks are stripped off. + def line_at(filename, line_number) # :nodoc: + @reload_on_change=nil unless defined?(@reload_on_change) + line = LineCache::getline(filename, line_number, @reload_on_change) + return "\n" unless line + return "#{line.gsub(/^\s+/, '').chomp}\n" + end + + # + # Activates the post-mortem mode. There are two ways of using it: + # + # == Global post-mortem mode + # By calling Debugger.post_mortem method without a block, you install + # at_exit hook that intercepts any unhandled by your script exceptions + # and enables post-mortem mode. + # + # == Local post-mortem mode + # + # If you know that a particular block of code raises an exception you can + # enable post-mortem mode by wrapping this block with Debugger.post_mortem, e.g. + # + # def offender + # raise 'error' + # end + # Debugger.post_mortem do + # ... + # offender + # ... + # end + def post_mortem + if block_given? + old_post_mortem = self.post_mortem? + begin + self.post_mortem = true + yield + rescue Exception => exp + handle_post_mortem(exp) + raise + ensure + self.post_mortem = old_post_mortem + end + else + return if post_mortem? + self.post_mortem = true + debug_at_exit do + handle_post_mortem($!) if $! && post_mortem? + end + end + end + + def handle_post_mortem(exp) + return if !exp || !exp.__debug_context || + exp.__debug_context.stack_size == 0 + Debugger.suspend + orig_tracing = Debugger.tracing, Debugger.current_context.tracing + Debugger.tracing = Debugger.current_context.tracing = false + Debugger.last_exception = exp + handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line) + ensure + Debugger.tracing, Debugger.current_context.tracing = orig_tracing + Debugger.resume + end + # private :handle_post_mortem + end + + class DebugThread # :nodoc: + end + + class ThreadsTable # :nodoc: + end + + # Debugger.start(options) -> bool + # Debugger.start(options) { ... } -> obj + # + # If it's called without a block it returns +true+, unless debugger + # was already started. If a block is given, it starts debugger and + # yields to block. When the block is finished executing it stops + # the debugger with Debugger.stop method. + # + # If a block is given, it starts debugger and yields to block. When + # the block is finished executing it stops the debugger with + # Debugger.stop method. Inside the block you will probably want to + # have a call to Debugger.debugger. For example: + # + # Debugger.start{debugger; foo} # Stop inside of foo + # + # Also, ruby-debug only allows + # one invocation of debugger at a time; nested Debugger.start's + # have no effect and you can't use this inside the debugger itself. + # + # Note that if you want to stop debugger, you must call + # Debugger.stop as many time as you called Debugger.start + # method. + # + # +options+ is a hash used to set various debugging options. + # Set :init true if you want to save ARGV and some variables which + # make a debugger restart possible. Only the first time :init is set true + # will values get set. Since ARGV is saved, you should make sure + # it hasn't been changed before the (first) call. + # Set :post_mortem true if you want to enter post-mortem debugging + # on an uncaught exception. Once post-mortem debugging is set, it can't + # be unset. + def start(options={}, &block) + options = Debugger::DEFAULT_START_SETTINGS.merge(options) + if options[:init] + Debugger.const_set('ARGV', ARGV.clone) unless + defined? Debugger::ARGV + Debugger.const_set('PROG_SCRIPT', $0) unless + defined? Debugger::PROG_SCRIPT + Debugger.const_set('INITIAL_DIR', Dir.pwd) unless + defined? Debugger::INITIAL_DIR + end + Debugger.tracing = options[:tracing] unless options[:tracing].nil? + retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block) + if options[:post_mortem] + post_mortem + end + return retval + end + module_function :start +end + +module Kernel + + # Enters the debugger in the current thread after _steps_ line events occur. + # Before entering the debugger startup script is read. + # + # Setting _steps_ to 0 will cause a break in the debugger subroutine + # and not wait for a line event to occur. You will have to go "up 1" + # in order to be back in your debugged program rather than the + # debugger. Settings _steps_ to 0 could be useful you want to stop + # right after the last statement in some scope, because the next + # step will take you out of some scope. + + # If a block is given (and the debugger hasn't been started, we run the + # block under the debugger. Alas, when a block is given, we can't support + # running the startup script or support the steps option. FIXME. + def debugger(steps = 1, &block) + if block + Debugger.start({}, &block) + else + Debugger.start unless Debugger.started? + Debugger.run_init_script(StringIO.new) + if 0 == steps + Debugger.current_context.stop_frame = 0 + else + Debugger.current_context.stop_next = steps + end + end + end + alias breakpoint debugger unless respond_to?(:breakpoint) + + # + # Returns a binding of n-th call frame + # + def binding_n(n = 0) + Debugger.skip do + Debugger.current_context.frame_binding(n+2) + end + end +end + +class Exception # :nodoc: + attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context +end + +class Module + # + # Wraps the +meth+ method with Debugger.start {...} block. + # + def debug_method(meth) + old_meth = "__debugee_#{meth}" + old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/ + alias_method old_meth.to_sym, meth + class_eval <<-EOD + def #{meth}(*args, &block) + Debugger.start do + debugger 2 + #{old_meth}(*args, &block) + end + end + EOD + end + + # + # Wraps the +meth+ method with Debugger.post_mortem {...} block. + # + def post_mortem_method(meth) + old_meth = "__postmortem_#{meth}" + old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/ + alias_method old_meth.to_sym, meth + class_eval <<-EOD + def #{meth}(*args, &block) + Debugger.start do |dbg| + dbg.post_mortem do + #{old_meth}(*args, &block) + end + end + end + EOD + end +end diff --git a/lib/ChangeLog b/lib/ChangeLog new file mode 100644 index 0000000..12c8f69 --- /dev/null +++ b/lib/ChangeLog @@ -0,0 +1,1065 @@ +2009-03-29 03:00 Rocky Bernstein + + * ChangeLog: Canonicalize breakpoint locations a little better. + More work should be done and more work should be done on the + testing side too. + +2009-03-11 23:42 Rocky Bernstein + + * ChangeLog: update texinfo for catch + +2008-11-25 02:43 Rocky Bernstein + + * ChangeLog: Frame without a frame number means frame 0, same as + gdb. We are now in 0.10.4 territory now. + +2008-11-16 00:14 Rocky Bernstein + + * ChangeLog: Add rdoc for rdebug script. + +2008-11-14 19:28 Rocky Bernstein + + * ruby-debug-base.rb: Go over documentation and revise. + +2008-11-14 15:32 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Move Debugger#debugger from base + to cli. Revert code in ruby_debug.c and block parameter in + debugger. cf. -> Compare with. Document Debugger.start better. + +2008-11-13 10:29 Rocky Bernstein + + * ChangeLog: Make Debugger.start{block} work if Debugger.started? + is false. Second try. + +2008-11-11 02:07 Rocky Bernstein + + * ChangeLog: Tweak truncated stack test since Ruby's caller doesn't + seem to include (tail?) recursive calls and we do. Get regression + tests working in light of recent changes. + +2008-11-10 01:48 Kent Sibilev + + * ruby-debug-base.rb: a little bit more readable + +2008-11-10 01:35 Kent Sibilev + + * ruby-debug-base.rb: Debugger.start must always call the passed + block + +2008-11-07 19:35 Rocky Bernstein + + * ChangeLog: Change truncated frame message. + +2008-11-07 10:39 Rocky Bernstein + + * ChangeLog: Add check to "where" to see if the call stack is + truncated; task #2354 + +2008-11-06 16:17 Rocky Bernstein + + * ChangeLog: #22698 Allow ruby-debug-base 0.x.y.z be compatible + with ruby-debug 0.x.y. + +2008-11-02 21:59 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Debugger.start with a block now + stops inside the block. Debugger.debugger with a block works like + Debugger.start with a block. + + The whole interface is hopelessly kludgy and needs to be redone. + +2008-10-26 14:54 Rocky Bernstein + + * ChangeLog: Doc typo. Add comment to remind me how to turn off + optimizationin extconf.rb + +2008-10-25 16:01 Rocky Bernstein + + * ChangeLog: Warn and add a "confirmation" when setting a + breakpoint on a file that is not loaded. Regression tests no + longer fail. + +2008-09-22 00:07 Rocky Bernstein + + * ruby-debug-base.rb: #22118 bug in showing variables post mortem. + Patch thanks to rubikitch. + Update pm.rb integration test. + +2008-09-03 17:29 Rocky Bernstein + + * ChangeLog: Show line numbers when $DEBUG is set. Patch #21772 + from Martin Krauskopf + +2008-07-07 07:11 Rocky Bernstein + + * ruby-debug-base.rb: Tracker [#20041] start erroneously moved to + Kernel - should be in + Debugger.start + +2008-06-20 06:46 Rocky Bernstein + + * ruby-debug-base.rb: trace.rb: add "trace var" + ruby-debug-base.rb: remove another undefined warning. + +2008-05-24 01:27 Rocky Bernstein + + * ChangeLog: Remove dup lines. + +2008-05-15 16:05 Rocky Bernstein + + * ChangeLog: Handle "catch nnn off" Forgotten there during r656. + From mkrauskopf [#20156]. + +2008-05-05 18:05 Rocky Bernstein + + * ChangeLog: make test-frame installation independent. Bug #19931 + +2008-04-29 13:37 Rocky Bernstein + + * ChangeLog: Test line number in "continue" command for validity. + +2008-04-28 16:16 Rocky Bernstein + + * ChangeLog: From Martin Krauskopf via patch #19779 + + Allow folks to configure Ruby used for CLI tests in the + test/config.yaml. The defaults are for native Ruby, so nothing + needs + to be done for ruby-debug. + + Developers of interfaces other than cli might override + config.yaml by + customized config.private.yaml which is ignored. So there will be + no + trash in e.g. 'svn st' output when developer customize the Ruby + to be + used. + + Handy for alternative interface implementations using + svn:externals. + +2008-04-22 02:49 Rocky Bernstein + + * ruby-debug-base.rb: Experiment with debugger(steps=0). Puts us in + the debugger call, but this may be the best we can do for now. + See tracker + #19639. + +2008-04-16 01:11 Rocky Bernstein + + * ChangeLog: In 0.10.2 now. Some work to cope systems without + readline. More work is needed. + Add test of "set autoeval." Undefined command message more + closely like gdb's. + +2008-04-10 08:49 Rocky Bernstein + + * ChangeLog: linecache is required by ruby-debug-base not + ruby-debug. Thanks Martin! + +2008-04-10 08:00 Rocky Bernstein + + * ChangeLog: Last change before 0.10.1 release. + +2008-04-10 02:03 Rocky Bernstein + + * ChangeLog: Cosmetic stuff: spelling corrections. Update node + structure so texinfo + doesn't complain. + +2008-04-08 14:52 Rocky Bernstein + + * ChangeLog: autorequire is deprecated and presumably no longer + needed + http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/182827 + +2008-04-07 00:36 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: ruby-debug-base.rb: document + Debugger.start parameters. + CHANGES: Revise what's happened + test-shortkey.el: A failing regression test because I think + rdebug-shortkey-mode + is not correct. + +2008-04-03 19:01 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Allow setting :post_mortem => true + from Debugger.start. + +2008-03-28 13:53 Rocky Bernstein + + * ChangeLog: Don't unconditionally turn on short-key mode when + annotations are on. Use rdebug-short-key-mode setting to decide. + +2008-03-23 17:47 Rocky Bernstein + + * ChangeLog: set.rb -> settings.rb since it's already one command + per file, and + remove another :nodoc. + Rakefile: split long line + +2008-03-18 16:05 Rocky Bernstein + + * ChangeLog: Fix bug in 'list' command when wrapping off the end. + test-finish.rb: tolerate buggy in Ruby versions <= 1.8.7. + +2008-03-13 02:15 Rocky Bernstein + + * ruby-debug-base.rb: INCOMPATIBLE CHANGE: "finish" works like gdb + - stop just before the + most recent method finishes. Will now accept a number which stops + that + many frames completed. (Note that return line numbers will be + funny, + the first line of the method until Ruby 1.8.7.) + +2008-03-10 13:28 Rocky Bernstein + + * ChangeLog: Dunno why we are now one line number less. So be it + (for now). + +2008-03-09 23:30 Rocky Bernstein + + * ChangeLog: For now we require the duplicate numbers on + conditionals. + +2008-03-02 04:20 Rocky Bernstein + + * ruby-debug-base.rb: Better error message for an invalid break + command. + +2008-02-28 05:06 Rocky Bernstein + + * ChangeLog: breakpoints.{cmd,right}: test for an invalid stopping + line number + rdebug-fns.el: move generic split-string-and-unquote from + rdebug-core. + rdebug-core.el: Add rdebug-common-init to replace + gud-common-init. Is + simpler, and finds files better via debugger output/annotations. + Fix bug in rdebug-setup-windows: gud-find-file can return nil, + and + we still need to set buf. + +2008-02-27 04:04 Rocky Bernstein + + * ruby-debug-base.rb: Slightly more robust handle_post_mortem. + +2008-02-26 17:31 Rocky Bernstein + + * ChangeLog: Go over source location positioning. 0 is now the + oldest (first) position. Add M-S-down and M-S-up for first and + last. More tests needed in test-fns.el and need to prompt on wrap + around. + +2008-02-26 00:57 Rocky Bernstein + + * ChangeLog: Fix bug in "info file xxx breakpoints". + +2008-02-24 16:36 Rocky Bernstein + + * ChangeLog: rdebug; make more Ruby 1.9 compatible. + +2008-02-24 16:14 Rocky Bernstein + + * ChangeLog: Minor changes. + rdbg.rb: don't need $DEBUG test any more + rdebug-regexp.el: go over with checkdoc + bin/rdebug: use PATH_SEPARATOR (for 'doze again) + +2008-02-24 04:51 Rocky Bernstein + + * ChangeLog: CLI: Add long help for "info file". + + test/test-help.rb: Make test failures easier to fix and more like + the + other tests. + + emacs/test: finish testing all of the funcitons in rdebug-fns.el + + rdebug-layouts.el: Make checkdoc clean. + rdebug-track.el: don't need to rename shell buffer. Do it as an + option only. + rdebug-secondary.el: get rid of hoaky buffer finding for at least + gud-comint-buf. (Should probably do others as well) + + DOC: Note weird line stopping locations. Describe what "ctrl" in + prompt means. + +2008-02-21 02:56 Rocky Bernstein + + * ChangeLog: Fringe for frame buffer the same as in source code. + Move + miscellaneous small functions to a new file. Reduce duplication + of + "chomp" code. + +2008-02-19 23:44 Rocky Bernstein + + * ChangeLog: rdebug-cmd.el: M-insert toggles shortkey mode in the + command buffer + rdebug: search for Ruby program if file is not found and no + SEPARATOR + chars in the filename + +2008-02-18 19:56 Rocky Bernstein + + * ChangeLog: Frame switching shouldn't be recorded in position + history ring. + +2008-02-17 13:57 Rocky Bernstein + + * ruby-debug-base.rb: Add Debugger.last_exception. Show exception + in post-mortem when "info program" + is issued. Reorganize list of major changes better. + +2008-02-13 21:47 Rocky Bernstein + + * ChangeLog: processor.rb: spelled "post-mortem" incorrectly in + prompt. + +2008-02-13 17:32 Rocky Bernstein + + * ChangeLog: Set up keys for comint-next-prompt and + comint-previous-prompt. + +2008-02-12 02:06 Rocky Bernstein + + * ChangeLog: Fix bug in "info thread verbose" which wasn't showing + full traceback. + +2008-02-09 15:48 Rocky Bernstein + + * ChangeLog: helper.rb Failed attempt to DRY tests more. But save + what we have + which may someday in the future be used to go further. Minus to + undercore in Data file names in preparation such time. (We'll use + the + filename as the test name). + + testing + +2008-02-06 16:15 Rocky Bernstein + + * ChangeLog: Add 'nowarn to find-file-noselect and test that we + don't get a warning. + +2008-02-05 01:41 Rocky Bernstein + + * ChangeLog: rdebug.el: Add a defgroup for rdebug so customization + in Emacs 23 is possible. + Some other minor doc fixes. + setshow.* make sure we don't have an $Id line that we have to + check against. + +2008-02-03 15:23 Rocky Bernstein + + * ChangeLog: Try to get testing a little more organized, although + more work should + be done: Create a data directory for comparison ("right") and + script + command ("cmd") files. Code is now more uniform (and should DRY'd + a + bit more). + +2008-02-02 23:10 Rocky Bernstein + + * ChangeLog: Remove commands in post-mortem which are not + applicable, e.g."step", + "next", "continue"... + + "No breakpoints have been set" is now an error message when + trying to + set a breakpoint. + + Add post-mortem test. + + Debug.init no longer exists. + +2008-02-02 09:27 Rocky Bernstein + + * ruby-debug-base.rb: Remove Debugger.init and fold options + parameter into Debugger.start. + Old Debugger.start has been renamed Deebugger.start_ + +2008-01-31 16:30 Rocky Bernstein + + * ChangeLog: Leave ruby_debug.c this way for now. + +2008-01-31 16:24 Rocky Bernstein + + * ChangeLog: ruby_debug.c: more adventures in exception handling + processor.rb: Removal of crash when annotate is on. Need to fix + the source of the + problem though. + +2008-01-31 15:16 Rocky Bernstein + + * ruby-debug-base.rb: Handle post-mortem and exception traceback + reporting in ruby-debug + +2008-01-30 17:01 Rocky Bernstein + + * ChangeLog: Add Command.find() to find a subcommand name. + condition.right: correct for breakpoint hit counts. + +2008-01-30 01:43 Rocky Bernstein + + * ChangeLog: Add number of times a breakpoint is hit like gdb does. + +2008-01-29 22:37 Rocky Bernstein + + * ChangeLog: Columnize breakpoint output. + +2008-01-29 11:20 Rocky Bernstein + + * ChangeLog: More annotate=2 fixes. + +2008-01-28 15:59 Rocky Bernstein + + * ChangeLog: Add info file breakpoints to show lines which we can + set a breakpoint on. + Revise so we chdir into SRC_DIR. + test-hist.rb is broken - will fix later. + +2008-01-25 12:11 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Add Debugger.init which intializes + things that rdebug does. This + allows a restart even though rdebug wasn't called initially. + +2008-01-22 23:15 Rocky Bernstein + + * ChangeLog: Allow "help info xxx". Add ability for long help on + "info" command. + Add "info break xx". + + test: remove test/unit class name conflicts. All the tests we + wrote + now get run. + +2008-01-19 19:28 Rocky Bernstein + + * ChangeLog: Move ruby-debug-base tests to base directory. Add a + binding_n regression test. + +2008-01-16 18:42 Rocky Bernstein + + * ChangeLog: Need to present source filename (__FILE__) as Ruby and + therefore breakpoint + sees it. + + +2008-01-16 02:19 Rocky Bernstein + + * ChangeLog, ruby-debug-base.rb: Line caching moved to an external + gem, linecache. We now require + version 0.2 of that or greater. + +2008-01-14 01:31 Rocky Bernstein + + * ChangeLog: Make rdebug-track work better in the face of prompt + and error annotations. + control.rb: need another test when rdebug not called initially. + +2008-01-13 21:51 Rocky Bernstein + + * ChangeLog: Some stack -> frame renaming + ext/breakpoint.c: put methods in alpha order (to help with + reference man) + breakpoints.rb: one print -> errmsg + +2008-01-13 18:13 Rocky Bernstein + + * ChangeLog: Create errmsg routine for error output, start tagging + error messages + as errors. Under annotate 3, output errors similar to gdb + --annotate + does (although still simplified). Have Emacs pick up debugger + error + annotations. + +2008-01-13 04:05 Rocky Bernstein + + * ChangeLog: Check validity of expressions in breakpoint conditions + and don't allow + enabling a syntactically invalid expression. + + Start noting messages which are errors via an errmsg routine. + +2008-01-11 10:26 Rocky Bernstein + + * ChangeLog: Document that ruby-debug resets $0. Align program + options in ref manual and --help. Alphabetize better. + +2008-01-10 22:56 Rocky Bernstein + + * ChangeLog: More correct $0 fix. Deal with the case ./ is + automatically added. + However this might not be right in all cases. + +2008-01-10 22:25 Rocky Bernstein + + * ChangeLog: Was gobbling arg in processing --emacs. Add test. + +2008-01-10 10:34 Rocky Bernstein + + * ChangeLog: Add condition command. + +2008-01-09 19:10 Rocky Bernstein + + * ChangeLog: Rakefile: rdebug.rb -> rdbg.el + rdebug-dbg.el: Add $Id$ + +2008-01-09 19:03 Rocky Bernstein + + * ChangeLog: Break out secondary buffer into their own file, and + also internal + debug code and general secondary commands. Secondary buffer code + removed from rdebug-cmd and moved into the appropriate file. + + rdebug-edit-variables-value is not defined so comment out for + now. + +2008-01-08 16:04 Rocky Bernstein + + * ChangeLog: Restore $: to the value it was before rdebug call. + +2008-01-07 20:38 Rocky Bernstein + + * ChangeLog: Add "var class". This means "var const .." can no + longer be abbreviated "var c"; use "var co" instead. + (Or "var const" or "var constant" + +2008-01-07 19:57 Rocky Bernstein + + * ChangeLog: Add class level variables to "info variables" + +2008-01-07 17:37 Rocky Bernstein + + * ChangeLog: Add "self" to list "info variables" spits out. + +2008-01-07 09:59 Rocky Bernstein + + * ChangeLog: --emacs sets width to 120. rdebug-core.el will reset + to 120 unless it's already that. + +2008-01-07 04:29 Rocky Bernstein + + * ChangeLog: Split out ChangeLogs better (I hope). + +2008-01-06 20:56 Rocky Bernstein + + * ChangeLog: test/*-emacs-basic*, tdebug: Add test of running in + Emacs without annotations. + + emacs/*.el: make regexp tests work again, move regexp to from + core to regexp. + Add an annotate regexp test. + + processor.rb: Remove some anotation print from bleeding into + output + when annotations are not wanted. Reinstate "Program finished" in + annotations and outside (rdebug). + +2008-01-06 18:55 Rocky Bernstein + + * ChangeLog: Create Processor class and subclass that. Perhaps a + mixin would be good. + Remove annotation output bleanding when annotate is off. + Try to reduce the mess annotations is adding to processor.rb + rdebug-core.el: fix indentation to pass the regression test + Anders added + Makefile.am: Add rdebug-source.el to distribution. + Make sure "rake test" + +2008-01-06 02:15 Rocky Bernstein + + * ChangeLog: Some work on saving state across a restart. More work + is needed on the + script command to get this working. The save-file name is now + optional. save.rb split off from script.rb Display expressions + and + some settings are now captured in the save/restore file. + Add interface.finalize - things that need to be done before quit + or + restart. + +2008-01-05 21:16 Rocky Bernstein + + * ChangeLog: More work to make annotate more like gdb's. + starting/stopping/exiting + should be more similar. Some code has been commented out until we + get + the Emacs interface to match. See "FIXME: ANNOTATE" in + processor.rb. + Also regression tests for output and annotate currently fail for + this + reason. + +2008-01-02 20:35 Rocky Bernstein + + * ChangeLog: helper.rb: add regexp for a position. TODO: add + parsing routine and use in + various commands + +2008-01-02 14:41 Rocky Bernstein + + * ChangeLog: processor.rb: Redo where starting/exiting annotations + are done. + rdebug.el: back off on setting output command for now. + +2008-01-01 15:23 Rocky Bernstein + + * ChangeLog: Fix --emacs to do --no-quit properly. + +2008-01-01 09:00 Rocky Bernstein + + * ChangeLog: Remove RDoc warnings caused because C files have been + split up. + +2008-01-01 05:51 Rocky Bernstein + + * ChangeLog: reindent -> indent. Makefile.am: wasn't including all + test files. + +2007-12-31 06:26 Rocky Bernstein + + * ChangeLog: Rakefile: add spit-off C files to ruby-debug-base gem. + +2007-12-31 06:23 Rocky Bernstein + + * ChangeLog: rdebug-test-cmd.el: Indentation + +2007-12-31 06:08 Rocky Bernstein + + * ChangeLog: Changes and more changes. + +2007-12-29 13:31 Rocky Bernstein + + * ChangeLog: Remove looping on quit. "-n" is broken so remove it + for now. + +2007-12-28 15:33 Rocky Bernstein + + * ChangeLog: info.rb: Incorrect test for no display expressions. + display.rb: Grammar thing. + processor.rb: Slightly cleaner code + test/* more/better tests. + +2007-12-27 21:03 Rocky Bernstein + + * ChangeLog: Be more agressive about resetting gud-last-frame and + gud-last-last-frame. These foul up tracking when debugging is + interrupted. + We probably need a special "reset" command. + +2007-12-26 18:35 Rocky Bernstein + + * ChangeLog: Version number games - maybe 0.10.1 is better. + +2007-12-25 23:40 Rocky Bernstein + + * ChangeLog: Add step- and step+. Document as well as the new + toggle command. + +2007-12-25 09:55 Rocky Bernstein + + * ChangeLog: Small doc fixes. + +2007-12-25 07:51 Rocky Bernstein + + * ChangeLog: Last commit before 0.10.0 release. + +2007-12-25 02:51 Rocky Bernstein + + * ChangeLog: breakpoints.*: main -> Object. Add bad Class name test + AUTHOR: Add Anders + README: note ruby-debug-extra. More precise (I think) + +2007-12-24 00:25 Rocky Bernstein + + * ChangeLog: Rakefile: set up gem unit test for ruby-debug-base. + Add file in test/ + so we could do the same for ruby-debug were it not for other + mysterious + problems. + +2007-12-23 17:33 Rocky Bernstein + + * ChangeLog: Go over packaging: + ChangeLogs for ruby-debug-base (in ext and lib) separate from CLI + ChangeLog + ChangeLogs now map userid to names + ruby-debug-base regression test included in ruby-debug-base + Columnize test separated. (It will disappear when ruby-debug + requires it + as an external) + +2007-12-16 21:31 Rocky Bernstein + + * ruby-debug-base.rb: Add "info variables test". + + ruby-debug-base.rb: Not sure how test(?M, file) ever worked + before but change + to use File.stat(file).mtime + info.rb: ignore debugger variables which are sometimes set. + +2007-12-10 03:23 Rocky Bernstein + + * ruby-debug-base.rb: doc changes. + +2007-06-26 07:05 Rocky Bernstein + + * ruby-debug-base.rb: Run .rdebugrc on Debugger.start. Look for + this in the current directory and run that instead the one in + $HOME if that exists. Again, inspired and compatible with gdb. + + rdebug: Check script for syntax errors before loading. We get + more informative errors and it doesn't look like rdebug is at + fault. + +2007-06-05 16:36 Kent Sibilev + + * ruby-debug-base.rb: code reorganization. + reverted 'run' command. + +2007-06-05 07:59 Kent Sibilev + + * ruby-debug-base.rb: restore post_mortem + +2007-06-02 15:01 Rocky Bernstein + + * ruby-debug-base.rb: lib/ruby-debug-base.rb: add Quit and Restart + exceptions which can reliably be used after the delayed exception + handling bug is fixed + emacs/rdebug-track.el and cli/ruby-debug/processor.rb: more + accurate line tracking in EMACS. When not in emacs should be more + like what was there. + +2007-06-01 21:57 Rocky Bernstein + + * ruby-debug-base.rb: parens around a print seems to give a + warning. Remove. + +2007-05-23 16:43 Rocky Bernstein + + * ruby-debug-base.rb: post_mortem: to test $! *before* running + debug_at_ext or else we may get an erroneous message: + ruby-debug-base.rb:162:in `current_context': Debugger.start is + not called yet. (RuntimeError) + + A simple test case to show the problem: + + "require rubygems" + "require ruby-debug" + Debugger.start + Debugger.post_mortem + exit # Causes us to incorrectly give the above error + +2007-05-15 20:22 Kent Sibilev + + * ruby-debug-base.rb: various fixes + +2007-04-27 23:21 Kent Sibilev + + * ruby-debug-base.rb: ditto + +2007-04-27 23:19 Kent Sibilev + + * ruby-debug-base.rb: add breakpoint method as an alias for + debugger in case breakpoint method is not defined already + +2007-03-25 01:03 Kent Sibilev + + * ruby-debug-base.rb: will start the debugger if necessary + +2007-03-24 18:17 Kent Sibilev + + * stable becomes the trunk + +2007-03-13 17:06 Kent Sibilev + + * fixed rdoc + +2007-03-01 23:44 Kent Sibilev + + * fixed post-mortem + +2007-02-27 08:02 Kent Sibilev + + * repackaging ruby-debug + +2007-02-23 20:56 Kent Sibilev + + * added an option for Debugger.debug_load to stop at the first line + of code + +2007-02-12 06:59 Kent Sibilev + + * added --emacs option + +2007-02-09 16:56 Kent Sibilev + + * in remote mode the debugger shouldn't stop inside of rdebug + script + +2007-02-09 06:20 Kent Sibilev + + * -- + +2007-02-09 01:00 Kent Sibilev + + * fixed code reloading + made 'reload on' as a part of the 'set' command + evaluate ~/.rdebugrc as an init script + +2007-02-07 02:42 Kent Sibilev + + * should use ignored? method to check for the debugger's thread + +2007-02-06 22:21 Kent Sibilev + + * + +2007-02-05 22:48 Kent Sibilev + + * -- + +2007-02-05 22:11 Kent Sibilev + + * fixed emacs integration + +2007-02-05 20:16 Kent Sibilev + + * fixed another issue where a bogus frame is being left in the + stack + +2007-02-04 23:36 Kent Sibilev + + * seg fault bugfixes + fixed suspend/resume + +2007-02-04 03:49 Kent Sibilev + + * A better fix for the segmentation fault + +2007-02-03 20:24 Kent Sibilev + + * fix seg fault by avoiding ruby's bug + fixed Context#resume + when handling post-mortem all threads must be suspended + +2007-02-02 18:47 Kent Sibilev + + * removed ambiguity with down command + +2007-02-01 23:48 Kent Sibilev + + * typo + +2007-02-01 22:15 Kent Sibilev + + * made eval command available from the control thread + +2007-02-01 07:22 Kent Sibilev + + * added setting command + added Context#suspended? method + dispay suspended status in the thread list + display frame starting from zero + +2007-01-31 21:13 Kent Sibilev + + * ditto + +2007-01-31 21:12 Kent Sibilev + + * fixed help command + +2007-01-31 19:39 Kent Sibilev + + * fixed frame count + added frame_self method to context + +2007-01-31 16:48 Kent Sibilev + + * removed all references to frames array + fixed post-mortem debugging + +2007-01-31 00:51 Kent Sibilev + + * removed obsolete frames usage + +2007-01-31 00:41 Kent Sibilev + + * refactored out frame class and preallocate stack + made local variable available even when bindings are not + collected. + +2007-01-28 20:25 Kent Sibilev + + * -- + +2007-01-28 06:22 Kent Sibilev + + * - Control thread is always started by rdebug script. + - Ability to specify negative frame number to frame commands. + Patch from R. Bernstein. + +2007-01-28 04:52 Kent Sibilev + + * added top frame caching + control thread is always started by rdebug script + +2007-01-27 01:43 Kent Sibilev + + * another performance optimization + +2007-01-26 20:28 Kent Sibilev + + * fixed #7484 + +2007-01-26 17:59 Kent Sibilev + + * revisited file name comparing procedure + +2007-01-26 09:03 Kent Sibilev + + * performance improvements + +2007-01-26 03:12 Kent Sibilev + + * added option to exclude collecting of frame bindings + +2007-01-24 18:33 Kent Sibilev + + * disable tracing when in post-mortem + added -x/--trace option to rdebug script + +2007-01-21 08:13 Kent Sibilev + + * + +2007-01-21 03:34 Kent Sibilev + + * assign an id to the breakpoint + +2007-01-21 01:20 Kent Sibilev + + * added post_mortem_method wrap method + +2006-12-21 20:16 Kent Sibilev + + * added 'restart' command + +2006-12-21 14:12 Kent Sibilev + + * made 'exit' an alias to 'quit' + fixed the interoperability problem with rspec + +2006-12-21 13:43 Kent Sibilev + + * fixed trace command in post-mortem mode + +2006-12-21 01:59 Kent Sibilev + + * initialize only once + +2006-12-21 01:08 Kent Sibilev + + * fixes irb help command + +2006-12-20 21:19 Kent Sibilev + + * check that debugger has been started + +2006-12-20 20:08 Kent Sibilev + + * added post-mortem option to rdebug + +2006-12-20 19:38 Kent Sibilev + + * initial support for post-mortem debugging + +2006-12-19 06:13 Kent Sibilev + + * removed 'run' alias + +2006-12-18 08:34 Kent Sibilev + + * added irb command + fixed source_for method + +2006-12-02 19:15 Kent Sibilev + + * added reload command + +2006-12-02 18:32 Kent Sibilev + + * fixed #6518 and #6545 + +2006-12-01 06:47 Kent Sibilev + + * + +2006-11-21 23:29 Kent Sibilev + + * ensure that on/off is the last on the line + +2006-11-16 00:04 Kent Sibilev + + * fixed debug_method for assignment methods + +2006-11-16 00:01 Kent Sibilev + + * added the new branch for the stable version + +2006-10-15 22:43 Kent Sibilev + + * branching a stable version + +2006-10-15 22:26 Kent Sibilev + + * ruby-debug.rb: remove unused require + uploaded new windows binary + +2006-10-15 19:02 Kent Sibilev + + * ruby-debug/commands/display.rb: remove unused constructor + +2006-10-15 16:54 Kent Sibilev + + * ruby-debug.rb, ruby-debug/commands/threads.rb: new logic of + context suspend/resume + +2006-10-15 07:36 Kent Sibilev + + * ruby-debug.rb, ruby-debug/lock.rb: fixed locking of debugger + threads + +2006-10-09 22:01 Kent Sibilev + + * ruby-debug/interface.rb: fixes for windows version + +2006-10-09 19:06 Kent Sibilev + + * ruby-debug.rb, ruby-debug/interface.rb: added Debugger.skip and + Debugger.debug_at_exit methods + +2006-10-09 16:44 Kent Sibilev + + * ., ruby-debug, ruby-debug.rb, ruby-debug/command.rb, + ruby-debug/commands, ruby-debug/commands/breakpoints.rb, + ruby-debug/commands/catchpoint.rb, + ruby-debug/commands/control.rb, ruby-debug/commands/display.rb, + ruby-debug/commands/eval.rb, ruby-debug/commands/frame.rb, + ruby-debug/commands/help.rb, ruby-debug/commands/list.rb, + ruby-debug/commands/method.rb, ruby-debug/commands/script.rb, + ruby-debug/commands/stepping.rb, ruby-debug/commands/threads.rb, + ruby-debug/commands/tmate.rb, ruby-debug/commands/trace.rb, + ruby-debug/commands/variables.rb, ruby-debug/interface.rb, + ruby-debug/lock.rb, ruby-debug/processor.rb: initial import + diff --git a/lib/ruby-debug-base.rb b/lib/ruby-debug-base.rb new file mode 100644 index 0000000..5995a66 --- /dev/null +++ b/lib/ruby-debug-base.rb @@ -0,0 +1,298 @@ +require 'ruby_debug.so' +require 'rubygems' +require 'linecache' + +module Debugger + + # Default options to Debugger.start + DEFAULT_START_SETTINGS = { + :init => true, # Set $0 and save ARGV? + :post_mortem => false, # post-mortem debugging on uncaught exception? + :tracing => nil # Debugger.tracing value. true/false resets, + # nil keeps the prior value + } unless defined?(DEFAULT_START_SETTINGS) + + class Context + def interrupt + self.stop_next = 1 + end + + alias __c_frame_binding frame_binding + def frame_binding(frame) + __c_frame_binding(frame) || hbinding(frame) + end + + private + + def hbinding(frame) + hash = frame_locals(frame) + code = hash.keys.map{|k| "#{k} = hash['#{k}']" unless k=='self' }.compact.join(';') + ';binding' + if obj = frame_self(frame) + obj.instance_eval code + else + eval code, TOPLEVEL_BINDING + end + end + + def handler + Debugger.handler or raise 'No interface loaded' + end + + def at_breakpoint(breakpoint) + handler.at_breakpoint(self, breakpoint) + end + + def at_catchpoint(excpt) + handler.at_catchpoint(self, excpt) + end + + def at_tracing(file, line) + handler.at_tracing(self, file, line) + end + + def at_line(file, line) + handler.at_line(self, file, line) + end + + def at_return(file, line) + handler.at_return(self, file, line) + end + end + + @reload_source_on_change = false + + class << self + # interface modules provide +handler+ object + attr_accessor :handler + + # if true, checks the modification time of source files and reloads if it was modified + attr_accessor :reload_source_on_change + + attr_accessor :last_exception + Debugger.last_exception = nil + + # + # Interrupts the current thread + # + def interrupt + current_context.interrupt + end + + # + # Interrupts the last debugged thread + # + def interrupt_last + if context = last_context + return nil unless context.thread.alive? + context.interrupt + end + context + end + + def source_reload + LineCache::clear_file_cache(true) + end + + # Get line +line_number+ from file named +filename+. Return "\n" + # there was a problem. Leaking blanks are stripped off. + def line_at(filename, line_number) # :nodoc: + @reload_on_change=nil unless defined?(@reload_on_change) + line = LineCache::getline(filename, line_number, @reload_on_change) + return "\n" unless line + return "#{line.gsub(/^\s+/, '').chomp}\n" + end + + # + # Activates the post-mortem mode. There are two ways of using it: + # + # == Global post-mortem mode + # By calling Debugger.post_mortem method without a block, you install + # at_exit hook that intercepts any unhandled by your script exceptions + # and enables post-mortem mode. + # + # == Local post-mortem mode + # + # If you know that a particular block of code raises an exception you can + # enable post-mortem mode by wrapping this block with Debugger.post_mortem, e.g. + # + # def offender + # raise 'error' + # end + # Debugger.post_mortem do + # ... + # offender + # ... + # end + def post_mortem + if block_given? + old_post_mortem = self.post_mortem? + begin + self.post_mortem = true + yield + rescue Exception => exp + handle_post_mortem(exp) + raise + ensure + self.post_mortem = old_post_mortem + end + else + return if post_mortem? + self.post_mortem = true + debug_at_exit do + handle_post_mortem($!) if $! && post_mortem? + end + end + end + + def handle_post_mortem(exp) + return if !exp || !exp.__debug_context || + exp.__debug_context.stack_size == 0 + Debugger.suspend + orig_tracing = Debugger.tracing, Debugger.current_context.tracing + Debugger.tracing = Debugger.current_context.tracing = false + Debugger.last_exception = exp + handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line) + ensure + Debugger.tracing, Debugger.current_context.tracing = orig_tracing + Debugger.resume + end + # private :handle_post_mortem + end + + class DebugThread # :nodoc: + end + + class ThreadsTable # :nodoc: + end + + # Debugger.start(options) -> bool + # Debugger.start(options) { ... } -> obj + # + # If it's called without a block it returns +true+, unless debugger + # was already started. If a block is given, it starts debugger and + # yields to block. When the block is finished executing it stops + # the debugger with Debugger.stop method. + # + # If a block is given, it starts debugger and yields to block. When + # the block is finished executing it stops the debugger with + # Debugger.stop method. Inside the block you will probably want to + # have a call to Debugger.debugger. For example: + # + # Debugger.start{debugger; foo} # Stop inside of foo + # + # Also, ruby-debug only allows + # one invocation of debugger at a time; nested Debugger.start's + # have no effect and you can't use this inside the debugger itself. + # + # Note that if you want to stop debugger, you must call + # Debugger.stop as many time as you called Debugger.start + # method. + # + # +options+ is a hash used to set various debugging options. + # Set :init true if you want to save ARGV and some variables which + # make a debugger restart possible. Only the first time :init is set true + # will values get set. Since ARGV is saved, you should make sure + # it hasn't been changed before the (first) call. + # Set :post_mortem true if you want to enter post-mortem debugging + # on an uncaught exception. Once post-mortem debugging is set, it can't + # be unset. + def start(options={}, &block) + options = Debugger::DEFAULT_START_SETTINGS.merge(options) + if options[:init] + Debugger.const_set('ARGV', ARGV.clone) unless + defined? Debugger::ARGV + Debugger.const_set('PROG_SCRIPT', $0) unless + defined? Debugger::PROG_SCRIPT + Debugger.const_set('INITIAL_DIR', Dir.pwd) unless + defined? Debugger::INITIAL_DIR + end + Debugger.tracing = options[:tracing] unless options[:tracing].nil? + retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block) + if options[:post_mortem] + post_mortem + end + return retval + end + module_function :start +end + +module Kernel + + # Enters the debugger in the current thread after _steps_ line events occur. + # Before entering the debugger startup script is read. + # + # Setting _steps_ to 0 will cause a break in the debugger subroutine + # and not wait for a line event to occur. You will have to go "up 1" + # in order to be back in your debugged program rather than the + # debugger. Settings _steps_ to 0 could be useful you want to stop + # right after the last statement in some scope, because the next + # step will take you out of some scope. + + # If a block is given (and the debugger hasn't been started, we run the + # block under the debugger. Alas, when a block is given, we can't support + # running the startup script or support the steps option. FIXME. + def debugger(steps = 1, &block) + if block + Debugger.start({}, &block) + else + Debugger.start unless Debugger.started? + Debugger.run_init_script(StringIO.new) + if 0 == steps + Debugger.current_context.stop_frame = 0 + else + Debugger.current_context.stop_next = steps + end + end + end + alias breakpoint debugger unless respond_to?(:breakpoint) + + # + # Returns a binding of n-th call frame + # + def binding_n(n = 0) + Debugger.skip do + Debugger.current_context.frame_binding(n+2) + end + end +end + +class Exception # :nodoc: + attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context +end + +class Module + # + # Wraps the +meth+ method with Debugger.start {...} block. + # + def debug_method(meth) + old_meth = "__debugee_#{meth}" + old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/ + alias_method old_meth.to_sym, meth + class_eval <<-EOD + def #{meth}(*args, &block) + Debugger.start do + debugger 2 + #{old_meth}(*args, &block) + end + end + EOD + end + + # + # Wraps the +meth+ method with Debugger.post_mortem {...} block. + # + def post_mortem_method(meth) + old_meth = "__postmortem_#{meth}" + old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/ + alias_method old_meth.to_sym, meth + class_eval <<-EOD + def #{meth}(*args, &block) + Debugger.start do |dbg| + dbg.post_mortem do + #{old_meth}(*args, &block) + end + end + end + EOD + end +end diff --git a/rdbg.rb b/rdbg.rb new file mode 100755 index 0000000..558e96b --- /dev/null +++ b/rdbg.rb @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby +#!/usr/bin/env ruby +# $Id: rdbg.rb 756 2008-03-13 02:15:04Z rockyb $ + +# Use this to run rdebug without installing it. We assume that the +# library directories are stored at the same level the directory +# this program. +module RDebugRunner + def runner(stdout=nil) + + # Add libraries to load path. + dirname=File.dirname(__FILE__) + libs = %w(ext lib cli) + libs.each { |lib| $:.unshift File.join(dirname, lib) } + + rdebug=ENV['RDEBUG'] || File.join(dirname, 'bin', 'rdebug') + if stdout + old_stdout = $stdout + $stdout.reopen(stdout) + else + old_stdout = nil + end + load(rdebug, true) + $stdout.reopen(old_stdout) if old_stdout + + # Remove those libraries we just added. + 1.upto(libs.size) {$:.shift} + end + module_function :runner +end +if __FILE__ == $0 + RDebugRunner.runner +end diff --git a/runner.sh b/runner.sh new file mode 100755 index 0000000..5a8f720 --- /dev/null +++ b/runner.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +ruby=${RUBY:-ruby} +dir=`dirname $0` +rdebug=${RDEBUG:-${dir}/bin/rdebug} +$ruby -I${dir}/ext:${dir}/lib:${dir}/cli -- $rdebug $* +exit $? diff --git a/svn2cl_usermap b/svn2cl_usermap new file mode 100644 index 0000000..5181cbd --- /dev/null +++ b/svn2cl_usermap @@ -0,0 +1,3 @@ +andersl:Anders Lindgren +kent:Kent Sibilev +rockyb:Rocky Bernstein diff --git a/test/.cvsignore b/test/.cvsignore new file mode 100644 index 0000000..b997925 --- /dev/null +++ b/test/.cvsignore @@ -0,0 +1 @@ +config.private.yaml diff --git a/test/.svn/README.txt b/test/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/test/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/test/.svn/dir-prop-base b/test/.svn/dir-prop-base new file mode 100644 index 0000000..b06d36d --- /dev/null +++ b/test/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 20 +config.private.yaml + +END diff --git a/test/.svn/dir-props b/test/.svn/dir-props new file mode 100644 index 0000000..b06d36d --- /dev/null +++ b/test/.svn/dir-props @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 20 +config.private.yaml + +END diff --git a/test/.svn/empty-file b/test/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/test/.svn/entries b/test/.svn/entries new file mode 100644 index 0000000..287fd4f --- /dev/null +++ b/test/.svn/entries @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/.svn/format b/test/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/test/.svn/format @@ -0,0 +1 @@ +4 diff --git a/test/.svn/prop-base/.cvsignore.svn-base b/test/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/bp_loop_issue.rb.svn-base b/test/.svn/prop-base/bp_loop_issue.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/bp_loop_issue.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/classes.rb.svn-base b/test/.svn/prop-base/classes.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/classes.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/config.yaml.svn-base b/test/.svn/prop-base/config.yaml.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/config.yaml.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/dollar-0.rb.svn-base b/test/.svn/prop-base/dollar-0.rb.svn-base new file mode 100644 index 0000000..462a03c --- /dev/null +++ b/test/.svn/prop-base/dollar-0.rb.svn-base @@ -0,0 +1,9 @@ +K 3 +add +V 14 +svn:executable +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/gcd-dbg-nox.rb.svn-base b/test/.svn/prop-base/gcd-dbg-nox.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/gcd-dbg-nox.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/gcd-dbg.rb.svn-base b/test/.svn/prop-base/gcd-dbg.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/gcd-dbg.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/gcd.rb.svn-base b/test/.svn/prop-base/gcd.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/gcd.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/helper.rb.svn-base b/test/.svn/prop-base/helper.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/helper.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/info-var-bug.rb.svn-base b/test/.svn/prop-base/info-var-bug.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/info-var-bug.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/info-var-bug2.rb.svn-base b/test/.svn/prop-base/info-var-bug2.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/info-var-bug2.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/null.rb.svn-base b/test/.svn/prop-base/null.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/null.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/output.rb.svn-base b/test/.svn/prop-base/output.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/output.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/pm-base.rb.svn-base b/test/.svn/prop-base/pm-base.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/pm-base.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/pm-bug.rb.svn-base b/test/.svn/prop-base/pm-bug.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/pm-bug.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/pm.rb.svn-base b/test/.svn/prop-base/pm.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/pm.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/raise.rb.svn-base b/test/.svn/prop-base/raise.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/raise.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/rdebug-save.1.svn-base b/test/.svn/prop-base/rdebug-save.1.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/rdebug-save.1.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/runall.svn-base b/test/.svn/prop-base/runall.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/runall.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/tdebug.rb.svn-base b/test/.svn/prop-base/tdebug.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/tdebug.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-annotate.rb.svn-base b/test/.svn/prop-base/test-annotate.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-annotate.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-break-bad.rb.svn-base b/test/.svn/prop-base/test-break-bad.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-break-bad.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-breakpoints.rb.svn-base b/test/.svn/prop-base/test-breakpoints.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-breakpoints.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-catch.rb.svn-base b/test/.svn/prop-base/test-catch.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-catch.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-condition.rb.svn-base b/test/.svn/prop-base/test-condition.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-condition.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-ctrl.rb.svn-base b/test/.svn/prop-base/test-ctrl.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-ctrl.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-display.rb.svn-base b/test/.svn/prop-base/test-display.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-display.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-dollar-0.rb.svn-base b/test/.svn/prop-base/test-dollar-0.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-dollar-0.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-edit.rb.svn-base b/test/.svn/prop-base/test-edit.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-edit.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-emacs-basic.rb.svn-base b/test/.svn/prop-base/test-emacs-basic.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-emacs-basic.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-enable.rb.svn-base b/test/.svn/prop-base/test-enable.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-enable.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-finish.rb.svn-base b/test/.svn/prop-base/test-finish.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-finish.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-frame.rb.svn-base b/test/.svn/prop-base/test-frame.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-frame.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-help.rb.svn-base b/test/.svn/prop-base/test-help.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-help.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-hist.rb.svn-base b/test/.svn/prop-base/test-hist.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-hist.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-info-thread.rb.svn-base b/test/.svn/prop-base/test-info-thread.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-info-thread.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-info-var.rb.svn-base b/test/.svn/prop-base/test-info-var.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-info-var.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-info.rb.svn-base b/test/.svn/prop-base/test-info.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-info.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-init.rb.svn-base b/test/.svn/prop-base/test-init.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-init.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-list.rb.svn-base b/test/.svn/prop-base/test-list.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-list.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-method.rb.svn-base b/test/.svn/prop-base/test-method.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-method.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-output.rb.svn-base b/test/.svn/prop-base/test-output.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-output.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-pm.rb.svn-base b/test/.svn/prop-base/test-pm.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-pm.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-quit.rb.svn-base b/test/.svn/prop-base/test-quit.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-quit.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-raise.rb.svn-base b/test/.svn/prop-base/test-raise.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-raise.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-save.rb.svn-base b/test/.svn/prop-base/test-save.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-save.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-setshow.rb.svn-base b/test/.svn/prop-base/test-setshow.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-setshow.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-source.rb.svn-base b/test/.svn/prop-base/test-source.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-source.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-stepping.rb.svn-base b/test/.svn/prop-base/test-stepping.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-stepping.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/test-trace.rb.svn-base b/test/.svn/prop-base/test-trace.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/prop-base/test-trace.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/prop-base/thread1.rb.svn-base b/test/.svn/prop-base/thread1.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/thread1.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/prop-base/trunc-call.rb.svn-base b/test/.svn/prop-base/trunc-call.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/prop-base/trunc-call.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/.cvsignore.svn-work b/test/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/bp_loop_issue.rb.svn-work b/test/.svn/props/bp_loop_issue.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/bp_loop_issue.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/classes.rb.svn-work b/test/.svn/props/classes.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/classes.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/config.yaml.svn-work b/test/.svn/props/config.yaml.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/config.yaml.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/dollar-0.rb.svn-work b/test/.svn/props/dollar-0.rb.svn-work new file mode 100644 index 0000000..462a03c --- /dev/null +++ b/test/.svn/props/dollar-0.rb.svn-work @@ -0,0 +1,9 @@ +K 3 +add +V 14 +svn:executable +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/gcd-dbg-nox.rb.svn-work b/test/.svn/props/gcd-dbg-nox.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/gcd-dbg-nox.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/gcd-dbg.rb.svn-work b/test/.svn/props/gcd-dbg.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/gcd-dbg.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/gcd.rb.svn-work b/test/.svn/props/gcd.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/gcd.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/helper.rb.svn-work b/test/.svn/props/helper.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/helper.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/info-var-bug.rb.svn-work b/test/.svn/props/info-var-bug.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/info-var-bug.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/info-var-bug2.rb.svn-work b/test/.svn/props/info-var-bug2.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/info-var-bug2.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/null.rb.svn-work b/test/.svn/props/null.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/null.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/output.rb.svn-work b/test/.svn/props/output.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/output.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/pm-base.rb.svn-work b/test/.svn/props/pm-base.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/pm-base.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/pm-bug.rb.svn-work b/test/.svn/props/pm-bug.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/pm-bug.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/pm.rb.svn-work b/test/.svn/props/pm.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/pm.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/raise.rb.svn-work b/test/.svn/props/raise.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/raise.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/rdebug-save.1.svn-work b/test/.svn/props/rdebug-save.1.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/rdebug-save.1.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/runall.svn-work b/test/.svn/props/runall.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/runall.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/tdebug.rb.svn-work b/test/.svn/props/tdebug.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/tdebug.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-annotate.rb.svn-work b/test/.svn/props/test-annotate.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-annotate.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-break-bad.rb.svn-work b/test/.svn/props/test-break-bad.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-break-bad.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-breakpoints.rb.svn-work b/test/.svn/props/test-breakpoints.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-breakpoints.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-catch.rb.svn-work b/test/.svn/props/test-catch.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-catch.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-condition.rb.svn-work b/test/.svn/props/test-condition.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-condition.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-ctrl.rb.svn-work b/test/.svn/props/test-ctrl.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-ctrl.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-display.rb.svn-work b/test/.svn/props/test-display.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-display.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-dollar-0.rb.svn-work b/test/.svn/props/test-dollar-0.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-dollar-0.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-edit.rb.svn-work b/test/.svn/props/test-edit.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-edit.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-emacs-basic.rb.svn-work b/test/.svn/props/test-emacs-basic.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-emacs-basic.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-enable.rb.svn-work b/test/.svn/props/test-enable.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-enable.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-finish.rb.svn-work b/test/.svn/props/test-finish.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-finish.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-frame.rb.svn-work b/test/.svn/props/test-frame.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-frame.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-help.rb.svn-work b/test/.svn/props/test-help.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-help.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-hist.rb.svn-work b/test/.svn/props/test-hist.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-hist.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-info-thread.rb.svn-work b/test/.svn/props/test-info-thread.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-info-thread.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-info-var.rb.svn-work b/test/.svn/props/test-info-var.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-info-var.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-info.rb.svn-work b/test/.svn/props/test-info.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-info.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-init.rb.svn-work b/test/.svn/props/test-init.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-init.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-list.rb.svn-work b/test/.svn/props/test-list.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-list.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-method.rb.svn-work b/test/.svn/props/test-method.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-method.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-output.rb.svn-work b/test/.svn/props/test-output.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-output.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-pm.rb.svn-work b/test/.svn/props/test-pm.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-pm.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-quit.rb.svn-work b/test/.svn/props/test-quit.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-quit.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-raise.rb.svn-work b/test/.svn/props/test-raise.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-raise.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-save.rb.svn-work b/test/.svn/props/test-save.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-save.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-setshow.rb.svn-work b/test/.svn/props/test-setshow.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-setshow.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-source.rb.svn-work b/test/.svn/props/test-source.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-source.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-stepping.rb.svn-work b/test/.svn/props/test-stepping.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-stepping.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/test-trace.rb.svn-work b/test/.svn/props/test-trace.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/.svn/props/test-trace.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/.svn/props/thread1.rb.svn-work b/test/.svn/props/thread1.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/thread1.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/props/trunc-call.rb.svn-work b/test/.svn/props/trunc-call.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/.svn/props/trunc-call.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/.svn/text-base/.cvsignore.svn-base b/test/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..b997925 --- /dev/null +++ b/test/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1 @@ +config.private.yaml diff --git a/test/.svn/text-base/bp_loop_issue.rb.svn-base b/test/.svn/text-base/bp_loop_issue.rb.svn-base new file mode 100644 index 0000000..abe072e --- /dev/null +++ b/test/.svn/text-base/bp_loop_issue.rb.svn-base @@ -0,0 +1,3 @@ +1.upto(2) { + sleep 0.01 +} diff --git a/test/.svn/text-base/classes.rb.svn-base b/test/.svn/text-base/classes.rb.svn-base new file mode 100644 index 0000000..7a874bd --- /dev/null +++ b/test/.svn/text-base/classes.rb.svn-base @@ -0,0 +1,11 @@ +class Mine + def initialize + @myvar = 'init' + end + def mymethod(a, b=5, &block) + end + def self.classmeth + end +end +me = Mine.new +metoo = Mine(new) diff --git a/test/.svn/text-base/config.yaml.svn-base b/test/.svn/text-base/config.yaml.svn-base new file mode 100644 index 0000000..2a3ab2b --- /dev/null +++ b/test/.svn/text-base/config.yaml.svn-base @@ -0,0 +1,8 @@ +# Do not commit personal changes here back to the repository. Create +# config.private.yaml which, if exists, is preferred to this one. + +# either should be on the $PATH or use full path +ruby: ruby + +# possibility to specify interpreter parameters +#ruby_params: -w diff --git a/test/.svn/text-base/dollar-0.rb.svn-base b/test/.svn/text-base/dollar-0.rb.svn-base new file mode 100644 index 0000000..9955e43 --- /dev/null +++ b/test/.svn/text-base/dollar-0.rb.svn-base @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby +# A test to see that rdebug set's $0 properly. +puts $0 +puts __FILE__ + diff --git a/test/.svn/text-base/gcd-dbg-nox.rb.svn-base b/test/.svn/text-base/gcd-dbg-nox.rb.svn-base new file mode 100644 index 0000000..5b84c6e --- /dev/null +++ b/test/.svn/text-base/gcd-dbg-nox.rb.svn-base @@ -0,0 +1,31 @@ +# This program is *NOT* supposed to be executable, but called +# via ruby (in order to test that restart provides a funky $:). +# This program is used to test that 'restart' works when we didn't call +# the debugger initially. + +TOP_SRC_DIR = File.join(File.expand_path(File.dirname(__FILE__), '..')) unless + defined?(TOP_SRC_DIR) + +$:.unshift File.join(TOP_SRC_DIR, 'ext') +$:.unshift File.join(TOP_SRC_DIR, 'lib') +$:.unshift File.join(TOP_SRC_DIR, 'cli') +require 'ruby-debug' +Debugger.init + +# GCD. We assume positive numbers +def gcd(a, b) + # Make: a <= b + debugger + if a > b + a, b = [b, a] + end + + return nil if a <= 0 + + if a == 1 or b-a == 0 + return a + end + return gcd(b-a, a) +end + +gcd(3,5) diff --git a/test/.svn/text-base/gcd-dbg.rb.svn-base b/test/.svn/text-base/gcd-dbg.rb.svn-base new file mode 100644 index 0000000..717518b --- /dev/null +++ b/test/.svn/text-base/gcd-dbg.rb.svn-base @@ -0,0 +1,30 @@ +#!/usr/bin/env ruby +# This program is used to test that 'restart' works when we didn't call +# the debugger initially. + +TOP_SRC_DIR = File.join(File.expand_path(File.dirname(__FILE__), "..")) unless + defined?(TOP_SRC_DIR) + +$:.unshift File.join(TOP_SRC_DIR, "ext") +$:.unshift File.join(TOP_SRC_DIR, "lib") +$:.unshift File.join(TOP_SRC_DIR, "cli") +require 'ruby-debug' +Debugger.start + +# GCD. We assume positive numbers +def gcd(a, b) + # Make: a <= b + debugger + if a > b + a, b = [b, a] + end + + return nil if a <= 0 + + if a == 1 or b-a == 0 + return a + end + return gcd(b-a, a) +end + +gcd(3,5) diff --git a/test/.svn/text-base/gcd.rb.svn-base b/test/.svn/text-base/gcd.rb.svn-base new file mode 100644 index 0000000..184b8df --- /dev/null +++ b/test/.svn/text-base/gcd.rb.svn-base @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby + +# GCD. We assume positive numbers +def gcd(a, b) + # Make: a <= b + if a > b + a, b = [b, a] + end + + return nil if a <= 0 + + if a == 1 or b-a == 0 + return a + end + return gcd(b-a, a) +end + +gcd(3,5) diff --git a/test/.svn/text-base/helper.rb.svn-base b/test/.svn/text-base/helper.rb.svn-base new file mode 100644 index 0000000..a675869 --- /dev/null +++ b/test/.svn/text-base/helper.rb.svn-base @@ -0,0 +1,143 @@ +# Some common routines used in testing. + +require 'fileutils' +require 'yaml' +# require 'diff/lcs' +# require 'diff/lcs/hunk' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +module TestHelper + + # FIXME: turn args into a hash. + def run_debugger(testname, args='', outfile=nil, filter=nil, old_code=false, + debug_pgm='tdebug.rb') + rightfile = File.join('data', "#{testname}.right") + + outfile = "#{testname}.out" unless outfile + + if File.exists?(outfile) + FileUtils.rm(outfile) + end + + ENV['RDEBUG'] = debug_pgm + + if old_code + cmd = "/bin/sh #{File.join('..', 'runner.sh')} #{args} >#{outfile}" + else + cmd = "#{"#{load_ruby} #{load_params} "}../rdbg.rb #{args} > #{outfile}" + end + puts "'#{cmd}'" if $DEBUG + output = `#{cmd}` + + got_lines = File.read(outfile).split(/\n/) + correct_lines = File.read(rightfile).split(/\n/) + filter.call(got_lines, correct_lines) if filter + if cheap_diff(got_lines, correct_lines) + FileUtils.rm(outfile) + return true + end + return false + end + + def cheap_diff(got_lines, correct_lines) + if $DEBUG + got_lines.each_with_index do |line, i| + printf "%3d %s\n", i+1, line + end + end + correct_lines.each_with_index do |line, i| + correct_lines[i].chomp! + if got_lines[i] != correct_lines[i] + puts "difference found at line #{i+1}" + puts "got : #{got_lines[i]}" + puts "need: #{correct_lines[i]}" + return false + end + end + if correct_lines.size != got_lines.size + puts("difference in number of lines: " + + "#{correct_lines.size} vs. #{got_lines.size}") + return false + end + return true + end + + # FIXME: using this causes the same test to get run several times + # and some tests fail probably because of a lack of environment isolation. + # Many tests follow a basic pattern: run the debugger with a given + # debugger script and compare output produced. The following creates + # this kind of test. + def add_test(base_name, src_dir, script_name=nil, cmd=nil, test_name=nil) + puts "+++ Adding #{base_name} ++++" if $DEBUG + test_name = base_name unless test_name + script_name = File.join('data', test_name + '.cmd') unless script_name + cmd = 'gcd.rb 3 5' unless cmd + eval <<-EOF + def test_#{test_name} + Dir.chdir(\"#{src_dir}\") do + assert_equal(true, + run_debugger(\"#{base_name}\", + \"--script #{script_name} -- #{cmd}\")) + end + end + EOF + end + module_function :add_test + + # Adapted from the Ruby Cookbook, Section 6.10: Comparing two files. + # def diff_as_string(rightfile, checkfile, format=:unified, context_lines=3) + # right_data = File.read(rightfile) + # check_data = File.read(checkfile) + # output = '' + # diffs = Diff::LCS.diff(right_data, check_data) + # return output if diffs.empty? + # oldhunk = hunk = nil + # file_length_difference = 0 + # diffs.each do |piece| + # begin + # hunk = Diff::LCS::Hunk.new(right_data, check_data, piece, + # context_lines, file_length_difference) + # next unless oldhunk + # + # # Hunks may overlap, which is why we need to be careful when our + # # diff includes lines of context. Otherwise, we might print + # # redundant lines. + # if (context_lines > 0) and hunk.overlaps?(oldhunk) + # hunk.unshift(oldhunk) + # else + # output << oldhunk.diff(format) + # end + # ensure + # oldhunk = hunk + # output << '\n' + # end + # end + + # # Handle the last remaining hunk + # output << oldhunk.diff(format) << '\n' + # end + + # Loads key from the _config_._yaml_ file. + def config_load(key, may_be_nil=false, default_value='') + conf = File.join('config.private.yaml') # try private first + conf = File.join('config.yaml') unless File.exists?(conf) + value = YAML.load_file(conf)[key] + assert_not_nil(value, "#{key} is set in config.yaml") unless may_be_nil + value || default_value + end + module_function :config_load + + def load_ruby + config_load('ruby', true) + end + module_function :load_ruby + + def load_params + config_load('ruby_params', true) + end + module_function :load_params + +end + diff --git a/test/.svn/text-base/info-var-bug.rb.svn-base b/test/.svn/text-base/info-var-bug.rb.svn-base new file mode 100644 index 0000000..9250e6e --- /dev/null +++ b/test/.svn/text-base/info-var-bug.rb.svn-base @@ -0,0 +1,47 @@ +class Lousy_inspect + attr_accessor :var + def inspect # An unhelpful inspect + throw "Foo" # Raises an exception + end + def initialize + @var = 'initialized' + end +end +class Lousy_inspect_and_to_s + attr_accessor :var + def inspect # An unhelpful inspect + throw "Foo" # Raises an exception + end + def to_s # An unhelpful to_s + throw "bar" # Raises an exception + end + def initialize + @var = 'initialized' # Something to inspect + end +end + +# Something that will be passed objects with +# bad inspect or to_s methods +class UnsuspectingClass + @@Const = 'A constant' + @@var = 'a class variable' + def initialize(a) + @a = a # "info locals" will try to use + # inspect or to_s here + @b = 5 + end +end +def test_Lousy_inspect + x = Lousy_inspect.new + return x +end +def test_lousy_inspect_and_to_s + x = Lousy_inspect_and_to_s.new + return x +end +x = test_Lousy_inspect +y = test_lousy_inspect_and_to_s +UnsuspectingClass.new(10) +UnsuspectingClass.new(x) +UnsuspectingClass.new(y) +y = 2 diff --git a/test/.svn/text-base/info-var-bug2.rb.svn-base b/test/.svn/text-base/info-var-bug2.rb.svn-base new file mode 100644 index 0000000..83d474e --- /dev/null +++ b/test/.svn/text-base/info-var-bug2.rb.svn-base @@ -0,0 +1,2 @@ +s = '<%= PRODUCT[:name] %>' +y = 0 diff --git a/test/.svn/text-base/null.rb.svn-base b/test/.svn/text-base/null.rb.svn-base new file mode 100644 index 0000000..47f0a27 --- /dev/null +++ b/test/.svn/text-base/null.rb.svn-base @@ -0,0 +1 @@ +# Nothing here. Move along. diff --git a/test/.svn/text-base/output.rb.svn-base b/test/.svn/text-base/output.rb.svn-base new file mode 100644 index 0000000..69fde1b --- /dev/null +++ b/test/.svn/text-base/output.rb.svn-base @@ -0,0 +1,2 @@ +puts "one" +puts "two" diff --git a/test/.svn/text-base/pm-base.rb.svn-base b/test/.svn/text-base/pm-base.rb.svn-base new file mode 100644 index 0000000..8d29f2f --- /dev/null +++ b/test/.svn/text-base/pm-base.rb.svn-base @@ -0,0 +1,22 @@ +#!/usr/bin/env ruby +# Test post-mortem handling using only ruby-debug-base. +src_dir = File.dirname(__FILE__) +%w(ext lib cli).each do |dir| + $:.unshift File.join(src_dir, '..', dir) +end +require 'ruby-debug-base' + +class CommandProcessor + def at_line(context, file, line) + puts 'file: %s, line: %s' % [ File.basename(file), line ] + exit! + end +end + +Debugger.start(:post_mortem => true) +Debugger.handler = CommandProcessor.new +def zero_div + 1/0 +end +zero_div + diff --git a/test/.svn/text-base/pm-bug.rb.svn-base b/test/.svn/text-base/pm-bug.rb.svn-base new file mode 100644 index 0000000..3ced249 --- /dev/null +++ b/test/.svn/text-base/pm-bug.rb.svn-base @@ -0,0 +1,3 @@ +a = 1 +@x = 2 +raise diff --git a/test/.svn/text-base/pm.rb.svn-base b/test/.svn/text-base/pm.rb.svn-base new file mode 100644 index 0000000..f8f0014 --- /dev/null +++ b/test/.svn/text-base/pm.rb.svn-base @@ -0,0 +1,11 @@ +#!/ursr/bin/env ruby +# Test Debugger.catchpoint and post-mortem handling +def zero_div + x = 5 + 1/0 +end +x = 2 +zero_div +raise RuntimeError +x = 3 + diff --git a/test/.svn/text-base/raise.rb.svn-base b/test/.svn/text-base/raise.rb.svn-base new file mode 100644 index 0000000..c6f3b51 --- /dev/null +++ b/test/.svn/text-base/raise.rb.svn-base @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby + +raise "abc" diff --git a/test/.svn/text-base/rdebug-save.1.svn-base b/test/.svn/text-base/rdebug-save.1.svn-base new file mode 100644 index 0000000..f759154 --- /dev/null +++ b/test/.svn/text-base/rdebug-save.1.svn-base @@ -0,0 +1,7 @@ +break gcd.rb:10 +break gcd.rb:12 if a > b +set autoeval on +set basename off +set debuggertesting off +set autolist off +set autoirb off diff --git a/test/.svn/text-base/runall.svn-base b/test/.svn/text-base/runall.svn-base new file mode 100644 index 0000000..634981b --- /dev/null +++ b/test/.svn/text-base/runall.svn-base @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +#-*- Ruby -*- +debug_opt = '-d ' if $DEBUG or 'd' == ARGV[0] +for file in Dir.glob("test-*.rb") do + puts "=" * 50 + puts "== running #{file}..." + system("ruby #{file}"); +end +if ARGV[0] == "really" + system("(cd test && ruby #{debug_opt}runall)") + system("(cd examples && ruby #{debug_opt}runall)") +end diff --git a/test/.svn/text-base/tdebug.rb.svn-base b/test/.svn/text-base/tdebug.rb.svn-base new file mode 100644 index 0000000..ae13f3e --- /dev/null +++ b/test/.svn/text-base/tdebug.rb.svn-base @@ -0,0 +1,252 @@ +#!/usr/bin/env ruby +# -*- Ruby -*- +# This is a hacked down copy of rdebug which can be used for testing +# FIXME: use the real rdebug script - DRY. + +require 'stringio' +require 'rubygems' +require 'optparse' +require "ostruct" + +TOP_SRC_DIR = File.join(File.dirname(__FILE__), "..") unless + defined?(TOP_SRC_DIR) + +$:.unshift File.join(TOP_SRC_DIR, "ext") +$:.unshift File.join(TOP_SRC_DIR, "lib") +$:.unshift File.join(TOP_SRC_DIR, "cli") + +def debug_program(options) + # Make sure Ruby script syntax checks okay. + # Otherwise we get a load message that looks like rdebug has + # a problem. + output = `ruby -c "#{Debugger::PROG_SCRIPT}" 2>&1` + if $?.exitstatus != 0 and RUBY_PLATFORM !~ /mswin/ + puts output + exit $?.exitstatus + end + print "\032\032starting\n" if Debugger.annotate and Debugger.annotate > 2 + unless options.no_rewrite_program + # Set $0 so things like __FILE == $0 work. + # A more reliable way to do this is to put $0 = __FILE__ *after* + # loading the script to be debugged. For this, adding a debug hook + # for the first time and then switching to the debug hook that's + # normally used would be helpful. Doing this would also help other + # first-time initializations such as reloading debugger state + # after a restart. + + # However This is just a little more than I want to take on right + # now, so I think I'll stick with the slightly hacky approach. + $RDEBUG_0 = $0 + + # cygwin does some sort of funky truncation on $0 ./abcdef => ./ab + # probably something to do with 3-letter extension truncation. + # The hacky workaround is to do slice assignment. Ugh. + d0 = if '.' == File.dirname(Debugger::PROG_SCRIPT) and + Debugger::PROG_SCRIPT[0..0] != '.' + File.join('.', Debugger::PROG_SCRIPT) + else + Debugger::PROG_SCRIPT + end + if $0.frozen? + $0 = d0 + else + $0[0..-1] = d0 + end + end + + # Record where we are we can know if the call stack has been + # truncated or not. + Debugger.start_sentinal=caller(0)[1] + + bt = Debugger.debug_load(Debugger::PROG_SCRIPT, !options.nostop, false) + if bt + if options.post_mortem + Debugger.handle_post_mortem(bt) + else + print bt.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n" + print "Uncaught exception: #{bt}\n" + end + end +end + +options = OpenStruct.new( + 'annotate' => false, + 'emacs' => false, + 'frame_bind' => false, + 'no-quit' => false, + 'no-stop' => false, + 'nx' => false, + 'post_mortem' => false, + 'script' => nil, + 'tracing' => false, + 'verbose_long'=> false, + 'wait' => false +) + +require "ruby-debug" + +program = File.basename($0) +opts = OptionParser.new do |opts| + opts.banner = < -- +EOB + opts.separator "" + opts.separator "Options:" + opts.on("-A", "--annotate LEVEL", Integer, "Set annotation level") do + |Debugger.annotate| + end + opts.on("-d", "--debug", "Set $DEBUG=true") {$DEBUG = true} + opts.on("--emacs-basic", "Activates basic Emacs mode") do + ENV['EMACS'] = '1' + options.emacs = true + end + opts.on("--keep-frame-binding", "Keep frame bindings") do + options.frame_bind = true + end + opts.on("-m", "--post-mortem", "Activate post-mortem mode") do + options.post_mortem = true + end + opts.on("--no-control", "Do not automatically start control thread") do + options.control = false + end + opts.on("--no-quit", "Do not quit when script finishes") do + options.noquit = true + end + opts.on("--no-stop", "Do not stop when script is loaded") do + options.nostop = true + end + opts.on("-nx", "Not run debugger initialization files (e.g. .rdebugrc") do + options.nx = true + end + opts.on("-I", "--include PATH", String, "Add PATH to $LOAD_PATH") do |path| + $LOAD_PATH.unshift(path) + end + opts.on("-r", "--require SCRIPT", String, + "Require the library, before executing your script") do |name| + if name == 'debug' + puts "ruby-debug is not compatible with Ruby's 'debug' library. This option is ignored." + else + require name + end + end + opts.on("--script FILE", String, "Name of the script file to run") do |options.script| + unless File.exists?(options.script) + puts "Script file '#{options.script}' is not found" + exit + end + end + opts.on("-x", "--trace", "Turn on line tracing") {options.tracing = true} + ENV['EMACS'] = nil unless options.emacs + opts.separator "" + opts.separator "Common options:" + opts.on_tail("--help", "Show this message") do + puts opts + exit + end + opts.on_tail("--version", + "Print the version") do + puts "ruby-debug #{Debugger::VERSION}" + exit + end + opts.on("--verbose", "Turn on verbose mode") do + $VERBOSE = true + options.verbose_long = true + end + opts.on_tail("-v", + "Print version number, then turn on verbose mode") do + puts "ruby-debug #{Debugger::VERSION}" + $VERBOSE = true + end +end + +begin + if not defined? Debugger::ARGV + Debugger::ARGV = ARGV.clone + end + rdebug_path = File.expand_path($0) + if RUBY_PLATFORM =~ /mswin/ + rdebug_path += '.cmd' unless rdebug_path =~ /\.cmd$/i + end + Debugger::RDEBUG_SCRIPT = rdebug_path + Debugger::RDEBUG_FILE = __FILE__ + Debugger::INITIAL_DIR = Dir.pwd + opts.parse! ARGV +rescue StandardError => e + puts opts + puts + puts e.message + exit(-1) +end + +if ARGV.empty? + exit if $VERBOSE and not options.verbose_long + puts opts + puts + puts 'Must specify a script to run' + exit(-1) +end + +# save script name +Debugger::PROG_SCRIPT = ARGV.shift + +# install interruption handler +trap('INT') { Debugger.interrupt_last } + +# set options +Debugger.wait_connection = false +Debugger.keep_frame_binding = options.frame_bind + +# Add Debugger trace hook. +Debugger.start + +# start control thread +Debugger.start_control(options.host, options.cport) if options.control + +# activate post-mortem +Debugger.post_mortem if options.post_mortem + +# Set up an interface to read commands from a debugger script file. +if options.script + Debugger.interface = Debugger::ScriptInterface.new(options.script, + STDOUT, true) +end +options.nostop = true if options.tracing +Debugger.tracing = options.tracing + +# Make sure Ruby script syntax checks okay. +# Otherwise we get a load message that looks like rdebug has +# a problem. +output = `ruby -c #{Debugger::PROG_SCRIPT} 2>&1` +if $?.exitstatus != 0 and RUBY_PLATFORM !~ /mswin/ + puts output + exit $?.exitstatus +end + +# load initrc script (e.g. .rdebugrc) +Debugger.run_init_script(StringIO.new) unless options.nx + +# run startup script if specified +if options.script + Debugger.run_script(options.script) +end +# activate post-mortem +Debugger.post_mortem if options.post_mortem +options.stop = false if options.tracing +Debugger.tracing = options.tracing + +if options.noquit + if Debugger.started? + until Debugger.stop do end + end + debug_program(options) + print "The program finished.\n" unless + Debugger.annotate.to_i > 1 # annotate has its own way + interface = Debugger::LocalInterface.new + # Not sure if ControlCommandProcessor is really the right + # thing to use. CommandProcessor requires a state. + processor = Debugger::ControlCommandProcessor.new(interface) + processor.process_commands +else + debug_program(options) +end diff --git a/test/.svn/text-base/test-annotate.rb.svn-base b/test/.svn/text-base/test-annotate.rb.svn-base new file mode 100644 index 0000000..27adff1 --- /dev/null +++ b/test/.svn/text-base/test-annotate.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' +require 'fileutils' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test annotate handling. +class TestAnnotate < Test::Unit::TestCase + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='annotate' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-break-bad.rb.svn-base b/test/.svn/text-base/test-break-bad.rb.svn-base new file mode 100644 index 0000000..f667ff7 --- /dev/null +++ b/test/.svn/text-base/test-break-bad.rb.svn-base @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test (mostly) invalid breakpoint commands +class TestBadBreak < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='break_bad' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end + + def test_break_loop + testname='break_loop_bug' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- bp_loop_issue.rb")) + end + end + +end diff --git a/test/.svn/text-base/test-breakpoints.rb.svn-base b/test/.svn/text-base/test-breakpoints.rb.svn-base new file mode 100644 index 0000000..aa7617e --- /dev/null +++ b/test/.svn/text-base/test-breakpoints.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test breakpoint commands +class TestBreakpoints < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='breakpoints' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-catch.rb.svn-base b/test/.svn/text-base/test-catch.rb.svn-base new file mode 100644 index 0000000..fc7ef91 --- /dev/null +++ b/test/.svn/text-base/test-catch.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test condition command +class TestBreakpoints < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='catch' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- pm.rb")) + end + end +end diff --git a/test/.svn/text-base/test-condition.rb.svn-base b/test/.svn/text-base/test-condition.rb.svn-base new file mode 100644 index 0000000..9fea498 --- /dev/null +++ b/test/.svn/text-base/test-condition.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test condition command +class TestBreakpoints < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='condition' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-ctrl.rb.svn-base b/test/.svn/text-base/test-ctrl.rb.svn-base new file mode 100644 index 0000000..213b592 --- /dev/null +++ b/test/.svn/text-base/test-ctrl.rb.svn-base @@ -0,0 +1,55 @@ +#!/usr/bin/env ruby + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug' ; Debugger.start + +require 'test/unit' +SRC_DIR = File.dirname(__FILE__) unless + defined?(SRC_DIR) +%w(ext lib cli).each do |dir| + $: << File.join(SRC_DIR, '..', dir) +end +require 'ruby_debug' +require File.join(SRC_DIR, '..', 'cli', 'ruby-debug') + +# Test Local Control Interface +class TestCtrl < Test::Unit::TestCase + + def cheap_diff(got_lines, correct_lines, outfile) + if correct_lines.size != got_lines.size + puts "Size difference #{correct_lines.size} vs. #{got_lines.size}" + File.open(outfile, 'w') {|f| f.puts got_lines} + return false + end + correct_lines.each_with_index do |line, i| + correct_lines[i].chomp! + if got_lines[i] != correct_lines[i] + puts "difference found at line #{i+1}" + puts "got : #{got_lines[i]}" + puts "need: #{correct_lines[i]}" + File.open(outfile, 'w') {|f| f.puts got_lines} + return false + end + end + end + + require 'stringio' + + # Test initial variables and setting/getting state. + def test_ctrl + ENV['COLUMNS'] = '80' + ENV['EMACS'] = nil + testbase = 'ctrl' + out = StringIO.new('', 'w') + Dir.chdir(SRC_DIR) do + script = File.join('data', "#{testbase}.cmd") + interface = Debugger::ScriptInterface.new(script, out) + processor = Debugger::ControlCommandProcessor.new(interface) + processor.process_commands + got_lines = out.string.split("\n") + right_file = File.join('data', "#{testbase}.right") + correct_lines = File.readlines(right_file) + assert cheap_diff(got_lines, correct_lines, "#{testbase}.out") + end + end +end diff --git a/test/.svn/text-base/test-display.rb.svn-base b/test/.svn/text-base/test-display.rb.svn-base new file mode 100644 index 0000000..4810a44 --- /dev/null +++ b/test/.svn/text-base/test-display.rb.svn-base @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Display commands +class TestDisplay < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test commands in display.rb + def test_basic + testname='display' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-dollar-0.rb.svn-base b/test/.svn/text-base/test-dollar-0.rb.svn-base new file mode 100644 index 0000000..8aa1346 --- /dev/null +++ b/test/.svn/text-base/test-dollar-0.rb.svn-base @@ -0,0 +1,45 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test --no-stop and $0 setting. +class TestDollar0 < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='breakpoints' + Dir.chdir(@@SRC_DIR) do + home_save = ENV['HOME'] + ENV['HOME'] = '.' + filter = Proc.new{|got_lines, correct_lines| + [got_lines, correct_lines].flatten.each do |s| + s.gsub!(/.*dollar-0.rb$/, 'dollar-0.rb') + end + } + + assert_equal(true, + run_debugger('dollar-0', + '-nx --no-stop ./dollar-0.rb', + nil, filter, false, '../bin/rdebug')) + # Ruby's __FILE__ seems to prepend ./ when no directory was added. + assert_equal(true, + run_debugger('dollar-0a', + '-nx --no-stop dollar-0.rb', + nil, filter, false, '../bin/rdebug')) + # Ruby's __FILE__ seems to prepend ./ when no directory was added. + assert_equal(true, + run_debugger('dollar-0b', + '-nx --no-stop ' + + File.join('..', 'test', 'dollar-0.rb'), + nil, filter, false, '../bin/rdebug')) + ENV['HOME'] = home_save + end + end +end diff --git a/test/.svn/text-base/test-edit.rb.svn-base b/test/.svn/text-base/test-edit.rb.svn-base new file mode 100644 index 0000000..27ef6c1 --- /dev/null +++ b/test/.svn/text-base/test-edit.rb.svn-base @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test 'edit' command handling. +class TestEdit < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='edit' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + ENV['EDITOR']='echo FAKE-EDITOR ' + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-emacs-basic.rb.svn-base b/test/.svn/text-base/test-emacs-basic.rb.svn-base new file mode 100644 index 0000000..c4c5518 --- /dev/null +++ b/test/.svn/text-base/test-emacs-basic.rb.svn-base @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start(:post_mortem => true) + +# Test the --emacs-basic option. +class TestEmacsBasic < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper.rb') + + include TestHelper + + def test_basic + testname='emacs_basic' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--emacs-basic --script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-enable.rb.svn-base b/test/.svn/text-base/test-enable.rb.svn-base new file mode 100644 index 0000000..db73ffe --- /dev/null +++ b/test/.svn/text-base/test-enable.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test enable and disable commands +class TestEnable < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='enable' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-finish.rb.svn-base b/test/.svn/text-base/test-finish.rb.svn-base new file mode 100644 index 0000000..4f452cf --- /dev/null +++ b/test/.svn/text-base/test-finish.rb.svn-base @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start + +# Test finish command +class TestFinish < Test::Unit::TestCase + + @@src_dir = File.dirname(__FILE__) unless + defined?(@@src_dir) + + require File.join(@@src_dir, 'helper') + include TestHelper + + def test_basic + testname='finish' + # Ruby 1.8.6 and earlier have a trace-line number bug for return + # statements. +# filter = Proc.new{|got_lines, correct_lines| +# [got_lines[31], got_lines[34]].flatten.each do |s| +# s.sub!(/gcd.rb:\d+/, 'gcd.rb:13') +# end +# got_lines[32] = 'return a' +# } + Dir.chdir(@@src_dir) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", + nil, nil)) + end + end +end diff --git a/test/.svn/text-base/test-frame.rb.svn-base b/test/.svn/text-base/test-frame.rb.svn-base new file mode 100644 index 0000000..c5f059f --- /dev/null +++ b/test/.svn/text-base/test-frame.rb.svn-base @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start(:post_mortem => true) + +# Test frame commands +class TestFrame < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test commands in frame.rb + def test_basic + testname='frame' + # Ruby 1.8.6 and earlier have a trace-line number bug for return + # statements. + filter = Proc.new{|got_lines, correct_lines| + [got_lines[11], correct_lines[11]].flatten.each do |s| + s.sub!(/in file ".*gcd.rb/, 'in file "gcd.rb') + end + } + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", + nil, filter)) + end + end +end diff --git a/test/.svn/text-base/test-help.rb.svn-base b/test/.svn/text-base/test-help.rb.svn-base new file mode 100644 index 0000000..460dd6c --- /dev/null +++ b/test/.svn/text-base/test-help.rb.svn-base @@ -0,0 +1,60 @@ +#!/usr/bin/env ruby + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug' ; Debugger.start + +require 'test/unit' +SRC_DIR = File.dirname(__FILE__) unless + defined?(SRC_DIR) +%w(ext lib cli).each do |dir| + $:.unshift File.join(SRC_DIR, '..', dir) +end +require 'ruby_debug' + +require File.join(SRC_DIR, '..', 'cli', 'ruby-debug') +$:.shift; $:.shift; $:.shift + +def cheap_diff(got_lines, correct_lines) + puts got_lines if $DEBUG + correct_lines.each_with_index do |line, i| + correct_lines[i].chomp! + if got_lines[i] != correct_lines[i] + puts "difference found at line #{i+1}" + puts "got : #{got_lines[i]}" + puts "need: #{correct_lines[i]}" + return false + end + if correct_lines.size != got_lines.size + puts("difference in number of lines: " + + "#{correct_lines.size} vs. #{got_lines.size}") + return false + end + return true + end +end + +# Test Help commands +class TestHelp < Test::Unit::TestCase + require 'stringio' + + # Test initial variables and setting/getting state. + def test_basic + testbase = 'help' + op = StringIO.new('', 'w') + Dir.chdir(SRC_DIR) do + script = File.join('data', "#{testbase}.cmd") + Debugger.const_set('Version', 'unit testing') + Debugger.run_script(script, op) + got_lines = op.string.split("\n") + right_file = File.join('data', "#{testbase}.right") + correct_lines = File.readlines(right_file) + result = cheap_diff(got_lines, correct_lines) + unless result + puts '-' * 80 + puts got_lines + puts '-' * 80 + end + assert result + end + end +end diff --git a/test/.svn/text-base/test-hist.rb.svn-base b/test/.svn/text-base/test-hist.rb.svn-base new file mode 100644 index 0000000..484394c --- /dev/null +++ b/test/.svn/text-base/test-hist.rb.svn-base @@ -0,0 +1,68 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test history commands + +class TestHistory < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + unless defined?(@@FILE_HISTORY) + @@FILE_HISTORY = '.rdebug_hist' + end + + def test_basic + + # Set up history file to read from. + ENV['HOME']=@@SRC_DIR + ENV['RDEBUG'] = nil + + debugger_commands = ['show commands', + 'set history save on', + 'show history', + 'quit unconditionally'] + debugger_output = 'test-history.out' + + Dir.chdir(@@SRC_DIR) do + correct_lines = File.read(File.join('data', 'history.right')).split(/\n/) + f = File.open(@@FILE_HISTORY, 'w') + correct_lines[0.. -(debugger_commands.length+1)].each do |line| + f.puts line + end + f.close + + # Now that we've set up a history file, run the debugger + # and check that it's reading that correctly. + debug_pgm=File.join('..', 'rdbg.rb') + debugged=File.join('gcd.rb') + IO.popen("#{debug_pgm} #{debugged} 3 5 >#{debugger_output}", 'w') do + |pipe| + debugger_commands.each do |cmd| + pipe.puts cmd + end + end + + # Compare output + got_lines = File.read(@@FILE_HISTORY).split(/\n/) + # FIXME: Disable for now. + assert true, 'FIXME' + return + if cheap_diff(got_lines, correct_lines) + assert true + FileUtils.rm(debugger_output) + FileUtils.rm(@@FILE_HISTORY) + else + assert nil, 'Output differs' + end + end + end +end + + diff --git a/test/.svn/text-base/test-info-thread.rb.svn-base b/test/.svn/text-base/test-info-thread.rb.svn-base new file mode 100644 index 0000000..d90cc8a --- /dev/null +++ b/test/.svn/text-base/test-info-thread.rb.svn-base @@ -0,0 +1,32 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test simple thread commands +class TestInfoThread < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='info-thread' + Dir.chdir(@@SRC_DIR) do + filter = Proc.new{|got_lines, correct_lines| + [got_lines, correct_lines].each do |a| + a.each do |s| + s.sub!(/Thread:0x[0-9a-f]+/, 'Thread:0x12345678') + end + end + } + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", nil, filter)) + end + end +end diff --git a/test/.svn/text-base/test-info-var.rb.svn-base b/test/.svn/text-base/test-info-var.rb.svn-base new file mode 100644 index 0000000..af06c78 --- /dev/null +++ b/test/.svn/text-base/test-info-var.rb.svn-base @@ -0,0 +1,47 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test info variables command +class TestInfoVar < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_info_variables + + Dir.chdir(@@SRC_DIR) do + + filter = Proc.new{|got_lines, correct_lines| + [got_lines[13-1], correct_lines[13-1]].each do |s| + s.sub!(/Mine:0x[0-9,a-f]+/, 'Mine:') + end + [got_lines, correct_lines].each do |a| + a.each do |s| + s.sub!(/Lousy_inspect:0x[0-9,a-f]+/, 'Lousy_inspect:') + s.sub!(/UnsuspectingClass:0x[0-9,a-f]+/, 'UnsuspectingClass:') + end + end + } + + testname='info-var' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- info-var-bug.rb", + nil, filter)) + testname='info-var-bug2' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- info-var-bug2.rb", + nil)) + + end + end +end diff --git a/test/.svn/text-base/test-info.rb.svn-base b/test/.svn/text-base/test-info.rb.svn-base new file mode 100644 index 0000000..dade3c8 --- /dev/null +++ b/test/.svn/text-base/test-info.rb.svn-base @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test info commands +class TestInfo < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test commands in info.rb + def test_basic + testname='info' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-init.rb.svn-base b/test/.svn/text-base/test-init.rb.svn-base new file mode 100644 index 0000000..bbc2394 --- /dev/null +++ b/test/.svn/text-base/test-init.rb.svn-base @@ -0,0 +1,43 @@ +#!/usr/bin/env ruby +require 'test/unit' +require 'rbconfig' +require File.join(File.dirname(__FILE__), 'helper.rb') + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Debugger.init and setting up ruby-debug variables +class TestDebuggerInit < Test::Unit::TestCase + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + def test_basic + debugger_output = 'test-init.out' + Dir.chdir(@@SRC_DIR) do + old_emacs = ENV['EMACS'] + old_columns = ENV['COLUMNS'] + ENV['EMACS'] = nil + ENV['COLUMNS'] = '120' + ruby = "#{TestHelper.load_ruby} #{TestHelper.load_params}" + IO.popen("#{ruby} ./gcd-dbg.rb 5 >#{debugger_output}", 'w') do |pipe| + pipe.puts 'p Debugger::PROG_SCRIPT' + pipe.puts 'show args' + pipe.puts 'quit unconditionally' + end + lines = File.open(debugger_output).readlines + ENV['EMACS'] = old_emacs + ENV['COLUMNS'] = old_columns + + right_file = case Config::CONFIG['host_os'] + when /^darwin/ + 'test-init-osx.right' + when /^cygwin/ + 'test-init-cygwin.right' + else + 'test-init.right' + end + expected = File.open(File.join('data', right_file)).readlines + assert_equal(expected, lines) + File.delete(debugger_output) if expected == lines + end + end +end diff --git a/test/.svn/text-base/test-list.rb.svn-base b/test/.svn/text-base/test-list.rb.svn-base new file mode 100644 index 0000000..12c2680 --- /dev/null +++ b/test/.svn/text-base/test-list.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test List commands +class TestList < Test::Unit::TestCase + + @@src_dir = File.dirname(__FILE__) + + require File.join(@@src_dir, 'helper') + include TestHelper + + # Test commands in list.rb + def test_basic + testname='list' + Dir.chdir(@@src_dir) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-method.rb.svn-base b/test/.svn/text-base/test-method.rb.svn-base new file mode 100644 index 0000000..a8da23b --- /dev/null +++ b/test/.svn/text-base/test-method.rb.svn-base @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start(:post_mortem => true) + +class TestMethod < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='method' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- classes.rb")) + begin + require 'methodsig' + testname='methodsig' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- classes.rb")) + rescue LoadError + puts "Skipping method sig test" + end + end + end +end diff --git a/test/.svn/text-base/test-output.rb.svn-base b/test/.svn/text-base/test-output.rb.svn-base new file mode 100644 index 0000000..9435113 --- /dev/null +++ b/test/.svn/text-base/test-output.rb.svn-base @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test 'starting' annotation. +class TestStartingAnnotate < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='output' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "-A 3 --script #{script} -- output.rb", + nil, nil, true)) + end + end +end diff --git a/test/.svn/text-base/test-pm.rb.svn-base b/test/.svn/text-base/test-pm.rb.svn-base new file mode 100644 index 0000000..cc646cc --- /dev/null +++ b/test/.svn/text-base/test-pm.rb.svn-base @@ -0,0 +1,59 @@ +#!/usr/bin/env ruby +require 'test/unit' +require 'rbconfig' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Post-mortem command +class TestPM < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test post-mortem handling + def test_basic + Dir.chdir(@@SRC_DIR) do +# filter = Proc.new{|got_lines, correct_lines| +# [got_lines[0], correct_lines[0]].each do |s| +# s.sub!(/tdebug.rb:\d+/, 'rdebug:999') +# end +# } + ENV['COLUMNS'] = '80' + testname='post-mortem' + script = File.join('data', testname + '.cmd') + testname += '-osx' if Config::CONFIG['host_os'] =~ /^darwin/ + assert_equal(true, + run_debugger(testname, + "--script #{script} --post-mortem pm.rb")) + end + end + + # Test post-mortem handling + def test_pm_next + Dir.chdir(@@SRC_DIR) do + ENV['COLUMNS'] = '80' + testname='post-mortem-next' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} --post-mortem pm.rb")) + end + end + + # Test Tracker #22118 post-mortem giving an error in show internal variables + def test_pm_iv_bug + Dir.chdir(@@SRC_DIR) do + ENV['COLUMNS'] = '80' + testname='pm-bug' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} --post-mortem pm-bug.rb")) + end + end + +end diff --git a/test/.svn/text-base/test-quit.rb.svn-base b/test/.svn/text-base/test-quit.rb.svn-base new file mode 100644 index 0000000..2a313b8 --- /dev/null +++ b/test/.svn/text-base/test-quit.rb.svn-base @@ -0,0 +1,30 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Quit command +class TestQuit < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='quit' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') +# filter = Proc.new{|got_lines, correct_lines| +# [got_lines[0], correct_lines[0]].each do |s| +# s.sub!(/tdebug.rb:\d+/, 'rdebug:999') +# end +# } + assert_equal(true, + run_debugger(testname, + "--script #{script} -- null.rb")) + end + end +end diff --git a/test/.svn/text-base/test-raise.rb.svn-base b/test/.svn/text-base/test-raise.rb.svn-base new file mode 100644 index 0000000..c111b9e --- /dev/null +++ b/test/.svn/text-base/test-raise.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Debugger.load handles uncaught exceptions in the debugged program. +class TestBreakpoints < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='raise' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- raise.rb")) + end + end +end diff --git a/test/.svn/text-base/test-save.rb.svn-base b/test/.svn/text-base/test-save.rb.svn-base new file mode 100644 index 0000000..6d8c6b0 --- /dev/null +++ b/test/.svn/text-base/test-save.rb.svn-base @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start(:post_mortem =>true) + +class TestSave < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test initial variables and setting/getting state. + def test_basic + testname='save' + filter = Proc.new{|got_lines, correct_lines| + got_lines.each do |s| + s.sub!(/2 file .*gcd.rb/, '2 file gcd.rb') + end + } + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", + nil, filter)) + end + end +end diff --git a/test/.svn/text-base/test-setshow.rb.svn-base b/test/.svn/text-base/test-setshow.rb.svn-base new file mode 100644 index 0000000..1710965 --- /dev/null +++ b/test/.svn/text-base/test-setshow.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +class TestSetShow < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test initial variables and setting/getting state. + def test_basic + testname='setshow' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-source.rb.svn-base b/test/.svn/text-base/test-source.rb.svn-base new file mode 100644 index 0000000..b6c1629 --- /dev/null +++ b/test/.svn/text-base/test-source.rb.svn-base @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test 'source' command handling. +class TestSource < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='source' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-stepping.rb.svn-base b/test/.svn/text-base/test-stepping.rb.svn-base new file mode 100644 index 0000000..8c4f404 --- /dev/null +++ b/test/.svn/text-base/test-stepping.rb.svn-base @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test that linetracing does something. +class TestStepping < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test commands in stepping.rb + def test_basic + testname='stepping' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/.svn/text-base/test-trace.rb.svn-base b/test/.svn/text-base/test-trace.rb.svn-base new file mode 100644 index 0000000..7e64ed0 --- /dev/null +++ b/test/.svn/text-base/test-trace.rb.svn-base @@ -0,0 +1,63 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test 'edit' command handling. +class TestEdit < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_trace_option + + filter = Proc.new{|got_lines, correct_lines| + got_lines.collect!{|l| l =~ /:gcd\.rb:/? l : nil}.compact! + } + + testname='trace' + Dir.chdir(@@SRC_DIR) do + assert_equal(true, + run_debugger(testname, + "-nx --trace gcd.rb 3 5", nil, filter)) + end + end + + def test_linetrace_command + + filter = Proc.new{|got_lines, correct_lines| + got_lines.collect!{|l| l !~ /:rdbg\.rb:/? l : nil}.compact! + } + + testname='linetrace' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", nil, + filter)) + + end + end + + def test_linetrace_plus_command + + filter = Proc.new{|got_lines, correct_lines| + got_lines.collect!{|l| l !~ /:rdbg\.rb:/? l : nil}.compact! + } + + testname='linetracep' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", nil, + filter)) + + end + end +end diff --git a/test/.svn/text-base/thread1.rb.svn-base b/test/.svn/text-base/thread1.rb.svn-base new file mode 100644 index 0000000..26bdf3b --- /dev/null +++ b/test/.svn/text-base/thread1.rb.svn-base @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +# Adapted from Programming Ruby 2nd Ed. p. 138 +require 'rubygems' + +unless defined?(Debugger) + puts "This program has to be called from the debugger" + exit 1 +end + +def fn(count, i) + sleep(rand(0.1)) + if 4 == i + debugger + end + Thread.current['mycount'] = count +end + +count = 0 +threads = [] +5.times do |i| + threads[i] = Thread.new do + fn(count, i) + count += 1 + end + end +threads.each {|t| t.join } diff --git a/test/.svn/text-base/trunc-call.rb.svn-base b/test/.svn/text-base/trunc-call.rb.svn-base new file mode 100644 index 0000000..d892d4f --- /dev/null +++ b/test/.svn/text-base/trunc-call.rb.svn-base @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# This program is used to test that 'restart' works when we didn't call +# the debugger initially. + +TOP_SRC_DIR = File.join(File.expand_path(File.dirname(__FILE__), "..")) unless + defined?(TOP_SRC_DIR) + +$:.unshift File.join(TOP_SRC_DIR, "ext") +$:.unshift File.join(TOP_SRC_DIR, "lib") +$:.unshift File.join(TOP_SRC_DIR, "cli") +require 'ruby-debug' + +# GCD. We assume positive numbers +def gcd(a, b) + # Make: a <= b + if a > b + a, b = [b, a] + end + if a==3 + Debugger.debugger + end + + return nil if a <= 0 + + if a == 1 or b-a == 0 + return a + end + return gcd(b-a, a) +end + +gcd(13,8) diff --git a/test/base/.svn/README.txt b/test/base/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/test/base/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/test/base/.svn/empty-file b/test/base/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/test/base/.svn/entries b/test/base/.svn/entries new file mode 100644 index 0000000..f02496e --- /dev/null +++ b/test/base/.svn/entries @@ -0,0 +1,49 @@ + + + + + + + + diff --git a/test/base/.svn/format b/test/base/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/test/base/.svn/format @@ -0,0 +1 @@ +4 diff --git a/test/base/.svn/prop-base/base.rb.svn-base b/test/base/.svn/prop-base/base.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/base/.svn/prop-base/base.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/base/.svn/prop-base/binding.rb.svn-base b/test/base/.svn/prop-base/binding.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/base/.svn/prop-base/binding.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/base/.svn/prop-base/catchpoint.rb.svn-base b/test/base/.svn/prop-base/catchpoint.rb.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/base/.svn/prop-base/catchpoint.rb.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/base/.svn/prop-base/load.rb.svn-base b/test/base/.svn/prop-base/load.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/base/.svn/prop-base/load.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/base/.svn/props/base.rb.svn-work b/test/base/.svn/props/base.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/base/.svn/props/base.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/base/.svn/props/binding.rb.svn-work b/test/base/.svn/props/binding.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/base/.svn/props/binding.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/base/.svn/props/catchpoint.rb.svn-work b/test/base/.svn/props/catchpoint.rb.svn-work new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/test/base/.svn/props/catchpoint.rb.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/test/base/.svn/props/load.rb.svn-work b/test/base/.svn/props/load.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/base/.svn/props/load.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/base/.svn/text-base/base.rb.svn-base b/test/base/.svn/text-base/base.rb.svn-base new file mode 100644 index 0000000..aefb56c --- /dev/null +++ b/test/base/.svn/text-base/base.rb.svn-base @@ -0,0 +1,74 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# Some tests of Debugger module in C extension ruby_debug +class TestRubyDebug < Test::Unit::TestCase + $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'ext') + require 'ruby_debug' + $:.shift + + # test current_context + def test_current_context + assert_equal(false, Debugger.started?, + 'debugger should not initially be started.') + Debugger.start_ + assert(Debugger.started?, + 'debugger should now be started.') + assert_equal(__LINE__, Debugger.current_context.frame_line) + assert_equal(nil, Debugger.current_context.frame_args_info, + 'no frame args info.') + assert_equal(Debugger.current_context.frame_file, + Debugger.current_context.frame_file(0)) + assert_equal(File.basename(__FILE__), + File.basename(Debugger.current_context.frame_file)) + assert_raises(ArgumentError) {Debugger.current_context.frame_file(1, 2)} + assert_raises(ArgumentError) {Debugger.current_context.frame_file(10)} + assert_equal(1, Debugger.current_context.stack_size) + assert_equal(TestRubyDebug, Debugger.current_context.frame_class) + assert_equal(false, Debugger.current_context.dead?, 'Not dead yet!') + Debugger.stop + assert_equal(false, Debugger.started?, + 'Debugger should no longer be started.') + end + + # Test initial variables and setting/getting state. + def test_debugger_base + assert_equal(false, Debugger.started?, + 'Debugger should not initially be started.') + Debugger.start_ + assert(Debugger.started?, + 'Debugger should now be started.') + assert_equal(false, Debugger.debug, + 'Debug variable should not be set.') + assert_equal(false, Debugger.post_mortem?, + 'Post mortem debugging should not be set.') + a = Debugger.contexts + assert_equal(1, a.size, + 'There should only be one context.') + assert_equal(Array, a.class, + 'Context should be an array.') + Debugger.stop + assert_equal(false, Debugger.started?, + 'debugger should no longer be started.') + end + + # Test breakpoint handling + def test_breakpoints + Debugger.start_ + assert_equal(0, Debugger.breakpoints.size, + 'There should not be any breakpoints set.') + brk = Debugger.add_breakpoint(__FILE__, 1) + assert_equal(Debugger::Breakpoint, brk.class, + 'Breakpoint should have been set and returned.') + assert_equal(1, Debugger.breakpoints.size, + 'There should now be one breakpoint set.') + Debugger.remove_breakpoint(0) + assert_equal(1, Debugger.breakpoints.size, + 'There should still be one breakpoint set.') + Debugger.remove_breakpoint(1) + assert_equal(0, Debugger.breakpoints.size, + 'There should no longer be any breakpoints set.') + Debugger.stop + end +end + diff --git a/test/base/.svn/text-base/binding.rb.svn-base b/test/base/.svn/text-base/binding.rb.svn-base new file mode 100644 index 0000000..23731fb --- /dev/null +++ b/test/base/.svn/text-base/binding.rb.svn-base @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby + +require 'test/unit' + +# Test binding_n command +class TestBinding < Test::Unit::TestCase + + SRC_DIR = File.expand_path(File.dirname(__FILE__)) unless + defined?(SRC_DIR) + %w(ext lib).each do |dir| + $:.unshift File.join(SRC_DIR, '..', '..', dir) + end + require File.join(SRC_DIR, '..', '..', 'lib', 'ruby-debug-base') + $:.shift; $:.shift + + def test_basic + def inside_fn + s = 'some other string' + b2 = Kernel::binding_n(1) + y2 = eval('s', b2) + assert_equal('this is a test', y2) + end + s = 'this is a test' + Debugger.start + b = Kernel::binding_n(0) + y = eval('s', b) + assert_equal(y, s) + inside_fn + Debugger.stop + end +end diff --git a/test/base/.svn/text-base/catchpoint.rb.svn-base b/test/base/.svn/text-base/catchpoint.rb.svn-base new file mode 100644 index 0000000..f7105db --- /dev/null +++ b/test/base/.svn/text-base/catchpoint.rb.svn-base @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# Test catchpoint in C ruby_debug extension. + +class TestRubyDebugCatchpoint < Test::Unit::TestCase + + $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'ext') + require 'ruby_debug' + $:.shift + + # test current_context + def test_catchpoints + assert_raise(RuntimeError) {Debugger.catchpoints} + Debugger.start_ + assert_equal({}, Debugger.catchpoints) + Debugger.add_catchpoint('ZeroDivisionError') + assert_equal({'ZeroDivisionError' => 0}, Debugger.catchpoints) + Debugger.add_catchpoint('RuntimeError') + assert_equal(['RuntimeError', 'ZeroDivisionError'], + Debugger.catchpoints.keys.sort) + Debugger.stop + end + +end + diff --git a/test/base/.svn/text-base/load.rb.svn-base b/test/base/.svn/text-base/load.rb.svn-base new file mode 100644 index 0000000..5168d8e --- /dev/null +++ b/test/base/.svn/text-base/load.rb.svn-base @@ -0,0 +1,40 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# Test of Debugger.debug_load in C extension ruby_debug.so +class TestDebugLoad < Test::Unit::TestCase + + @@src_dir = File.dirname(__FILE__) + $:.unshift File.join(@@src_dir, '..', '..', 'ext') + require 'ruby_debug' + $:.shift + + class << self + def at_line(file, line) + @@at_line = [File.basename(file), line] + end + end + + Debugger::PROG_SCRIPT = File.join(@@src_dir, '..', 'gcd.rb') + + class Debugger::Context + def at_line(file, line) + TestDebugLoad::at_line(file, line) + end + end + + def test_debug_load + # Without stopping + bt = Debugger.debug_load(Debugger::PROG_SCRIPT, false) + assert_equal(nil, bt) + # With stopping + bt = Debugger.debug_load(Debugger::PROG_SCRIPT, true) + assert_equal(nil, bt) + assert_equal(['gcd.rb', 4], @@at_line) + + # Test that we get a proper backtrace on a script that raises 'abc' + prog_script = File.join(@@src_dir, '..', 'raise.rb') + bt = Debugger.debug_load(prog_script, false) + assert_equal(bt.to_s, 'abc') + end +end diff --git a/test/base/base.rb b/test/base/base.rb new file mode 100755 index 0000000..aefb56c --- /dev/null +++ b/test/base/base.rb @@ -0,0 +1,74 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# Some tests of Debugger module in C extension ruby_debug +class TestRubyDebug < Test::Unit::TestCase + $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'ext') + require 'ruby_debug' + $:.shift + + # test current_context + def test_current_context + assert_equal(false, Debugger.started?, + 'debugger should not initially be started.') + Debugger.start_ + assert(Debugger.started?, + 'debugger should now be started.') + assert_equal(__LINE__, Debugger.current_context.frame_line) + assert_equal(nil, Debugger.current_context.frame_args_info, + 'no frame args info.') + assert_equal(Debugger.current_context.frame_file, + Debugger.current_context.frame_file(0)) + assert_equal(File.basename(__FILE__), + File.basename(Debugger.current_context.frame_file)) + assert_raises(ArgumentError) {Debugger.current_context.frame_file(1, 2)} + assert_raises(ArgumentError) {Debugger.current_context.frame_file(10)} + assert_equal(1, Debugger.current_context.stack_size) + assert_equal(TestRubyDebug, Debugger.current_context.frame_class) + assert_equal(false, Debugger.current_context.dead?, 'Not dead yet!') + Debugger.stop + assert_equal(false, Debugger.started?, + 'Debugger should no longer be started.') + end + + # Test initial variables and setting/getting state. + def test_debugger_base + assert_equal(false, Debugger.started?, + 'Debugger should not initially be started.') + Debugger.start_ + assert(Debugger.started?, + 'Debugger should now be started.') + assert_equal(false, Debugger.debug, + 'Debug variable should not be set.') + assert_equal(false, Debugger.post_mortem?, + 'Post mortem debugging should not be set.') + a = Debugger.contexts + assert_equal(1, a.size, + 'There should only be one context.') + assert_equal(Array, a.class, + 'Context should be an array.') + Debugger.stop + assert_equal(false, Debugger.started?, + 'debugger should no longer be started.') + end + + # Test breakpoint handling + def test_breakpoints + Debugger.start_ + assert_equal(0, Debugger.breakpoints.size, + 'There should not be any breakpoints set.') + brk = Debugger.add_breakpoint(__FILE__, 1) + assert_equal(Debugger::Breakpoint, brk.class, + 'Breakpoint should have been set and returned.') + assert_equal(1, Debugger.breakpoints.size, + 'There should now be one breakpoint set.') + Debugger.remove_breakpoint(0) + assert_equal(1, Debugger.breakpoints.size, + 'There should still be one breakpoint set.') + Debugger.remove_breakpoint(1) + assert_equal(0, Debugger.breakpoints.size, + 'There should no longer be any breakpoints set.') + Debugger.stop + end +end + diff --git a/test/base/binding.rb b/test/base/binding.rb new file mode 100755 index 0000000..23731fb --- /dev/null +++ b/test/base/binding.rb @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby + +require 'test/unit' + +# Test binding_n command +class TestBinding < Test::Unit::TestCase + + SRC_DIR = File.expand_path(File.dirname(__FILE__)) unless + defined?(SRC_DIR) + %w(ext lib).each do |dir| + $:.unshift File.join(SRC_DIR, '..', '..', dir) + end + require File.join(SRC_DIR, '..', '..', 'lib', 'ruby-debug-base') + $:.shift; $:.shift + + def test_basic + def inside_fn + s = 'some other string' + b2 = Kernel::binding_n(1) + y2 = eval('s', b2) + assert_equal('this is a test', y2) + end + s = 'this is a test' + Debugger.start + b = Kernel::binding_n(0) + y = eval('s', b) + assert_equal(y, s) + inside_fn + Debugger.stop + end +end diff --git a/test/base/catchpoint.rb b/test/base/catchpoint.rb new file mode 100755 index 0000000..f7105db --- /dev/null +++ b/test/base/catchpoint.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# Test catchpoint in C ruby_debug extension. + +class TestRubyDebugCatchpoint < Test::Unit::TestCase + + $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'ext') + require 'ruby_debug' + $:.shift + + # test current_context + def test_catchpoints + assert_raise(RuntimeError) {Debugger.catchpoints} + Debugger.start_ + assert_equal({}, Debugger.catchpoints) + Debugger.add_catchpoint('ZeroDivisionError') + assert_equal({'ZeroDivisionError' => 0}, Debugger.catchpoints) + Debugger.add_catchpoint('RuntimeError') + assert_equal(['RuntimeError', 'ZeroDivisionError'], + Debugger.catchpoints.keys.sort) + Debugger.stop + end + +end + diff --git a/test/base/load.rb b/test/base/load.rb new file mode 100644 index 0000000..5168d8e --- /dev/null +++ b/test/base/load.rb @@ -0,0 +1,40 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# Test of Debugger.debug_load in C extension ruby_debug.so +class TestDebugLoad < Test::Unit::TestCase + + @@src_dir = File.dirname(__FILE__) + $:.unshift File.join(@@src_dir, '..', '..', 'ext') + require 'ruby_debug' + $:.shift + + class << self + def at_line(file, line) + @@at_line = [File.basename(file), line] + end + end + + Debugger::PROG_SCRIPT = File.join(@@src_dir, '..', 'gcd.rb') + + class Debugger::Context + def at_line(file, line) + TestDebugLoad::at_line(file, line) + end + end + + def test_debug_load + # Without stopping + bt = Debugger.debug_load(Debugger::PROG_SCRIPT, false) + assert_equal(nil, bt) + # With stopping + bt = Debugger.debug_load(Debugger::PROG_SCRIPT, true) + assert_equal(nil, bt) + assert_equal(['gcd.rb', 4], @@at_line) + + # Test that we get a proper backtrace on a script that raises 'abc' + prog_script = File.join(@@src_dir, '..', 'raise.rb') + bt = Debugger.debug_load(prog_script, false) + assert_equal(bt.to_s, 'abc') + end +end diff --git a/test/bp_loop_issue.rb b/test/bp_loop_issue.rb new file mode 100644 index 0000000..abe072e --- /dev/null +++ b/test/bp_loop_issue.rb @@ -0,0 +1,3 @@ +1.upto(2) { + sleep 0.01 +} diff --git a/test/classes.rb b/test/classes.rb new file mode 100644 index 0000000..7a874bd --- /dev/null +++ b/test/classes.rb @@ -0,0 +1,11 @@ +class Mine + def initialize + @myvar = 'init' + end + def mymethod(a, b=5, &block) + end + def self.classmeth + end +end +me = Mine.new +metoo = Mine(new) diff --git a/test/cli/.svn/README.txt b/test/cli/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/test/cli/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/test/cli/.svn/empty-file b/test/cli/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/test/cli/.svn/entries b/test/cli/.svn/entries new file mode 100644 index 0000000..db9fc5c --- /dev/null +++ b/test/cli/.svn/entries @@ -0,0 +1,16 @@ + + + + + diff --git a/test/cli/.svn/format b/test/cli/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/test/cli/.svn/format @@ -0,0 +1 @@ +4 diff --git a/test/cli/commands/.svn/README.txt b/test/cli/commands/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/test/cli/commands/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/test/cli/commands/.svn/empty-file b/test/cli/commands/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/test/cli/commands/.svn/entries b/test/cli/commands/.svn/entries new file mode 100644 index 0000000..7a5b99c --- /dev/null +++ b/test/cli/commands/.svn/entries @@ -0,0 +1,25 @@ + + + + + + diff --git a/test/cli/commands/.svn/format b/test/cli/commands/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/test/cli/commands/.svn/format @@ -0,0 +1 @@ +4 diff --git a/test/cli/commands/.svn/prop-base/catchpoint_test.rb.svn-base b/test/cli/commands/.svn/prop-base/catchpoint_test.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/cli/commands/.svn/prop-base/catchpoint_test.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/cli/commands/.svn/props/catchpoint_test.rb.svn-work b/test/cli/commands/.svn/props/catchpoint_test.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/cli/commands/.svn/props/catchpoint_test.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/cli/commands/.svn/text-base/catchpoint_test.rb.svn-base b/test/cli/commands/.svn/text-base/catchpoint_test.rb.svn-base new file mode 100644 index 0000000..e9921c5 --- /dev/null +++ b/test/cli/commands/.svn/text-base/catchpoint_test.rb.svn-base @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby + +require 'test/unit' + +class TestCatchCommand < Test::Unit::TestCase + + base_dir = File.expand_path(File.join(File.dirname(__FILE__), + '..', '..', '..')) + + %w(ext lib cli).each do |dir| + $: << File.join(base_dir, dir) + end + + require File.join(base_dir, 'cli', 'ruby-debug') + + class MockState + attr_accessor :message + def context; end + def confirm(msg); true end + def print(*args) + @message = *args + end + end + + # regression test for bug #20156 + def test_catch_does_not_blow_up + state = MockState.new + catch_cmd = Debugger::CatchCommand.new(state) + assert(catch_cmd.match('catch off')) + catch(:debug_error) do + catch_cmd.execute + end + assert_equal(nil, state.message) + end + +end diff --git a/test/cli/commands/catchpoint_test.rb b/test/cli/commands/catchpoint_test.rb new file mode 100644 index 0000000..e9921c5 --- /dev/null +++ b/test/cli/commands/catchpoint_test.rb @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby + +require 'test/unit' + +class TestCatchCommand < Test::Unit::TestCase + + base_dir = File.expand_path(File.join(File.dirname(__FILE__), + '..', '..', '..')) + + %w(ext lib cli).each do |dir| + $: << File.join(base_dir, dir) + end + + require File.join(base_dir, 'cli', 'ruby-debug') + + class MockState + attr_accessor :message + def context; end + def confirm(msg); true end + def print(*args) + @message = *args + end + end + + # regression test for bug #20156 + def test_catch_does_not_blow_up + state = MockState.new + catch_cmd = Debugger::CatchCommand.new(state) + assert(catch_cmd.match('catch off')) + catch(:debug_error) do + catch_cmd.execute + end + assert_equal(nil, state.message) + end + +end diff --git a/test/cli/commands/unit/.svn/README.txt b/test/cli/commands/unit/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/test/cli/commands/unit/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/test/cli/commands/unit/.svn/empty-file b/test/cli/commands/unit/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/test/cli/commands/unit/.svn/entries b/test/cli/commands/unit/.svn/entries new file mode 100644 index 0000000..1e3b392 --- /dev/null +++ b/test/cli/commands/unit/.svn/entries @@ -0,0 +1,22 @@ + + + + + diff --git a/test/cli/commands/unit/.svn/format b/test/cli/commands/unit/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/test/cli/commands/unit/.svn/format @@ -0,0 +1 @@ +4 diff --git a/test/cli/commands/unit/.svn/prop-base/regexp.rb.svn-base b/test/cli/commands/unit/.svn/prop-base/regexp.rb.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/cli/commands/unit/.svn/prop-base/regexp.rb.svn-base @@ -0,0 +1 @@ +END diff --git a/test/cli/commands/unit/.svn/props/regexp.rb.svn-work b/test/cli/commands/unit/.svn/props/regexp.rb.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/cli/commands/unit/.svn/props/regexp.rb.svn-work @@ -0,0 +1 @@ +END diff --git a/test/cli/commands/unit/.svn/text-base/regexp.rb.svn-base b/test/cli/commands/unit/.svn/text-base/regexp.rb.svn-base new file mode 100644 index 0000000..76ed41d --- /dev/null +++ b/test/cli/commands/unit/.svn/text-base/regexp.rb.svn-base @@ -0,0 +1,42 @@ +require 'test/unit' + + +class TestCommandREs < Test::Unit::TestCase + base_dir=File.expand_path(File.join(File.dirname(__FILE__), + '..', '..', '..', '..', + 'cli', 'ruby-debug')) + require File.join(base_dir, 'command') + require File.join(base_dir, 'commands', 'frame') + include Debugger + + def test_quit + c = QuitCommand.new(nil) + assert c.regexp.match('quit') + assert c.regexp.match('q') + assert c.regexp.match('quit!') + assert c.regexp.match('q!') + assert c.regexp.match('quit unconditionally') + assert c.regexp.match('exit') + assert c.regexp.match('exit!') + end + + def test_up + c = UpCommand.new(nil) + assert c.regexp.match('up') + assert c.regexp.match('up 2') + assert c.regexp.match('up 2+5') + assert c.regexp.match('u') + assert c.regexp.match('u 2') + assert_equal nil, c.regexp.match('ufoo') + end + + def test_down + c = DownCommand.new(nil) + assert c.regexp.match('down') + assert c.regexp.match('down 2') + assert_equal(nil, c.regexp.match('d 2')) + assert_equal(nil, c.regexp.match('d')) + assert_equal(nil, c.regexp.match('dow')) + end +end + diff --git a/test/cli/commands/unit/regexp.rb b/test/cli/commands/unit/regexp.rb new file mode 100644 index 0000000..76ed41d --- /dev/null +++ b/test/cli/commands/unit/regexp.rb @@ -0,0 +1,42 @@ +require 'test/unit' + + +class TestCommandREs < Test::Unit::TestCase + base_dir=File.expand_path(File.join(File.dirname(__FILE__), + '..', '..', '..', '..', + 'cli', 'ruby-debug')) + require File.join(base_dir, 'command') + require File.join(base_dir, 'commands', 'frame') + include Debugger + + def test_quit + c = QuitCommand.new(nil) + assert c.regexp.match('quit') + assert c.regexp.match('q') + assert c.regexp.match('quit!') + assert c.regexp.match('q!') + assert c.regexp.match('quit unconditionally') + assert c.regexp.match('exit') + assert c.regexp.match('exit!') + end + + def test_up + c = UpCommand.new(nil) + assert c.regexp.match('up') + assert c.regexp.match('up 2') + assert c.regexp.match('up 2+5') + assert c.regexp.match('u') + assert c.regexp.match('u 2') + assert_equal nil, c.regexp.match('ufoo') + end + + def test_down + c = DownCommand.new(nil) + assert c.regexp.match('down') + assert c.regexp.match('down 2') + assert_equal(nil, c.regexp.match('d 2')) + assert_equal(nil, c.regexp.match('d')) + assert_equal(nil, c.regexp.match('dow')) + end +end + diff --git a/test/config.yaml b/test/config.yaml new file mode 100644 index 0000000..2a3ab2b --- /dev/null +++ b/test/config.yaml @@ -0,0 +1,8 @@ +# Do not commit personal changes here back to the repository. Create +# config.private.yaml which, if exists, is preferred to this one. + +# either should be on the $PATH or use full path +ruby: ruby + +# possibility to specify interpreter parameters +#ruby_params: -w diff --git a/test/data/.svn/README.txt b/test/data/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/test/data/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/test/data/.svn/empty-file b/test/data/.svn/empty-file new file mode 100644 index 0000000..e69de29 diff --git a/test/data/.svn/entries b/test/data/.svn/entries new file mode 100644 index 0000000..f67e270 --- /dev/null +++ b/test/data/.svn/entries @@ -0,0 +1,697 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/data/.svn/format b/test/data/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/test/data/.svn/format @@ -0,0 +1 @@ +4 diff --git a/test/data/.svn/prop-base/annotate.cmd.svn-base b/test/data/.svn/prop-base/annotate.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/annotate.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/annotate.right.svn-base b/test/data/.svn/prop-base/annotate.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/annotate.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/break_bad.cmd.svn-base b/test/data/.svn/prop-base/break_bad.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/break_bad.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/break_bad.right.svn-base b/test/data/.svn/prop-base/break_bad.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/break_bad.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/break_loop_bug.cmd.svn-base b/test/data/.svn/prop-base/break_loop_bug.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/break_loop_bug.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/break_loop_bug.right.svn-base b/test/data/.svn/prop-base/break_loop_bug.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/break_loop_bug.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/breakpoints.cmd.svn-base b/test/data/.svn/prop-base/breakpoints.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/breakpoints.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/breakpoints.right.svn-base b/test/data/.svn/prop-base/breakpoints.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/breakpoints.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/catch.cmd.svn-base b/test/data/.svn/prop-base/catch.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/catch.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/catch.right.svn-base b/test/data/.svn/prop-base/catch.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/catch.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/condition.cmd.svn-base b/test/data/.svn/prop-base/condition.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/condition.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/condition.right.svn-base b/test/data/.svn/prop-base/condition.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/condition.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/ctrl.cmd.svn-base b/test/data/.svn/prop-base/ctrl.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/ctrl.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/ctrl.right.svn-base b/test/data/.svn/prop-base/ctrl.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/ctrl.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/display.cmd.svn-base b/test/data/.svn/prop-base/display.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/display.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/display.right.svn-base b/test/data/.svn/prop-base/display.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/display.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/dollar-0.right.svn-base b/test/data/.svn/prop-base/dollar-0.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/dollar-0.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/dollar-0a.right.svn-base b/test/data/.svn/prop-base/dollar-0a.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/dollar-0a.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/dollar-0b.right.svn-base b/test/data/.svn/prop-base/dollar-0b.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/dollar-0b.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/edit.cmd.svn-base b/test/data/.svn/prop-base/edit.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/edit.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/edit.right.svn-base b/test/data/.svn/prop-base/edit.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/edit.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/emacs_basic.cmd.svn-base b/test/data/.svn/prop-base/emacs_basic.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/emacs_basic.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/emacs_basic.right.svn-base b/test/data/.svn/prop-base/emacs_basic.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/emacs_basic.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/enable.cmd.svn-base b/test/data/.svn/prop-base/enable.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/enable.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/enable.right.svn-base b/test/data/.svn/prop-base/enable.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/enable.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/finish.cmd.svn-base b/test/data/.svn/prop-base/finish.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/finish.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/finish.right.svn-base b/test/data/.svn/prop-base/finish.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/finish.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/frame.cmd.svn-base b/test/data/.svn/prop-base/frame.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/frame.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/frame.right.svn-base b/test/data/.svn/prop-base/frame.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/frame.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/help.cmd.svn-base b/test/data/.svn/prop-base/help.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/help.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/help.right.svn-base b/test/data/.svn/prop-base/help.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/help.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/history.right.svn-base b/test/data/.svn/prop-base/history.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/history.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/info-thread.cmd.svn-base b/test/data/.svn/prop-base/info-thread.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/info-thread.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/info-thread.right.svn-base b/test/data/.svn/prop-base/info-thread.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/info-thread.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/info-var-bug2.cmd.svn-base b/test/data/.svn/prop-base/info-var-bug2.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/info-var-bug2.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/info-var-bug2.right.svn-base b/test/data/.svn/prop-base/info-var-bug2.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/info-var-bug2.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/info-var.cmd.svn-base b/test/data/.svn/prop-base/info-var.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/info-var.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/info-var.right.svn-base b/test/data/.svn/prop-base/info-var.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/info-var.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/info.cmd.svn-base b/test/data/.svn/prop-base/info.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/info.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/info.right.svn-base b/test/data/.svn/prop-base/info.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/info.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/linetrace.cmd.svn-base b/test/data/.svn/prop-base/linetrace.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/linetrace.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/linetrace.right.svn-base b/test/data/.svn/prop-base/linetrace.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/linetrace.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/linetracep.cmd.svn-base b/test/data/.svn/prop-base/linetracep.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/linetracep.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/linetracep.right.svn-base b/test/data/.svn/prop-base/linetracep.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/linetracep.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/list.cmd.svn-base b/test/data/.svn/prop-base/list.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/list.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/list.right.svn-base b/test/data/.svn/prop-base/list.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/list.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/method.cmd.svn-base b/test/data/.svn/prop-base/method.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/method.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/method.right.svn-base b/test/data/.svn/prop-base/method.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/method.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/methodsig.cmd.svn-base b/test/data/.svn/prop-base/methodsig.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/methodsig.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/methodsig.right.svn-base b/test/data/.svn/prop-base/methodsig.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/methodsig.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/noquit.right.svn-base b/test/data/.svn/prop-base/noquit.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/noquit.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/output.cmd.svn-base b/test/data/.svn/prop-base/output.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/output.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/output.right.svn-base b/test/data/.svn/prop-base/output.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/output.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/pm-bug.cmd.svn-base b/test/data/.svn/prop-base/pm-bug.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/pm-bug.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/pm-bug.right.svn-base b/test/data/.svn/prop-base/pm-bug.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/pm-bug.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/post-mortem-next.cmd.svn-base b/test/data/.svn/prop-base/post-mortem-next.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/post-mortem-next.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/post-mortem-next.right.svn-base b/test/data/.svn/prop-base/post-mortem-next.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/post-mortem-next.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/post-mortem-osx.right.svn-base b/test/data/.svn/prop-base/post-mortem-osx.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/post-mortem-osx.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/post-mortem.cmd.svn-base b/test/data/.svn/prop-base/post-mortem.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/post-mortem.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/post-mortem.right.svn-base b/test/data/.svn/prop-base/post-mortem.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/post-mortem.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/quit.cmd.svn-base b/test/data/.svn/prop-base/quit.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/quit.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/quit.right.svn-base b/test/data/.svn/prop-base/quit.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/quit.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/raise.cmd.svn-base b/test/data/.svn/prop-base/raise.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/raise.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/raise.right.svn-base b/test/data/.svn/prop-base/raise.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/raise.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/save.cmd.svn-base b/test/data/.svn/prop-base/save.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/save.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/save.right.svn-base b/test/data/.svn/prop-base/save.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/save.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/setshow.cmd.svn-base b/test/data/.svn/prop-base/setshow.cmd.svn-base new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/test/data/.svn/prop-base/setshow.cmd.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/test/data/.svn/prop-base/setshow.right.svn-base b/test/data/.svn/prop-base/setshow.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/setshow.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/source.cmd.svn-base b/test/data/.svn/prop-base/source.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/source.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/source.right.svn-base b/test/data/.svn/prop-base/source.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/source.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/stepping.cmd.svn-base b/test/data/.svn/prop-base/stepping.cmd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/stepping.cmd.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/stepping.right.svn-base b/test/data/.svn/prop-base/stepping.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/stepping.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/test-init-cygwin.right.svn-base b/test/data/.svn/prop-base/test-init-cygwin.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/test-init-cygwin.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/test-init-osx.right.svn-base b/test/data/.svn/prop-base/test-init-osx.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/test-init-osx.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/test-init.right.svn-base b/test/data/.svn/prop-base/test-init.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/test-init.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/prop-base/trace.right.svn-base b/test/data/.svn/prop-base/trace.right.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/prop-base/trace.right.svn-base @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/annotate.cmd.svn-work b/test/data/.svn/props/annotate.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/annotate.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/annotate.right.svn-work b/test/data/.svn/props/annotate.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/annotate.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/break_bad.cmd.svn-work b/test/data/.svn/props/break_bad.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/break_bad.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/break_bad.right.svn-work b/test/data/.svn/props/break_bad.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/break_bad.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/break_loop_bug.cmd.svn-work b/test/data/.svn/props/break_loop_bug.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/break_loop_bug.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/break_loop_bug.right.svn-work b/test/data/.svn/props/break_loop_bug.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/break_loop_bug.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/breakpoints.cmd.svn-work b/test/data/.svn/props/breakpoints.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/breakpoints.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/breakpoints.right.svn-work b/test/data/.svn/props/breakpoints.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/breakpoints.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/catch.cmd.svn-work b/test/data/.svn/props/catch.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/catch.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/catch.right.svn-work b/test/data/.svn/props/catch.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/catch.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/condition.cmd.svn-work b/test/data/.svn/props/condition.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/condition.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/condition.right.svn-work b/test/data/.svn/props/condition.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/condition.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/ctrl.cmd.svn-work b/test/data/.svn/props/ctrl.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/ctrl.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/ctrl.right.svn-work b/test/data/.svn/props/ctrl.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/ctrl.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/display.cmd.svn-work b/test/data/.svn/props/display.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/display.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/display.right.svn-work b/test/data/.svn/props/display.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/display.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/dollar-0.right.svn-work b/test/data/.svn/props/dollar-0.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/dollar-0.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/dollar-0a.right.svn-work b/test/data/.svn/props/dollar-0a.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/dollar-0a.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/dollar-0b.right.svn-work b/test/data/.svn/props/dollar-0b.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/dollar-0b.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/edit.cmd.svn-work b/test/data/.svn/props/edit.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/edit.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/edit.right.svn-work b/test/data/.svn/props/edit.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/edit.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/emacs_basic.cmd.svn-work b/test/data/.svn/props/emacs_basic.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/emacs_basic.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/emacs_basic.right.svn-work b/test/data/.svn/props/emacs_basic.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/emacs_basic.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/enable.cmd.svn-work b/test/data/.svn/props/enable.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/enable.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/enable.right.svn-work b/test/data/.svn/props/enable.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/enable.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/finish.cmd.svn-work b/test/data/.svn/props/finish.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/finish.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/finish.right.svn-work b/test/data/.svn/props/finish.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/finish.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/frame.cmd.svn-work b/test/data/.svn/props/frame.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/frame.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/frame.right.svn-work b/test/data/.svn/props/frame.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/frame.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/help.cmd.svn-work b/test/data/.svn/props/help.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/help.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/help.right.svn-work b/test/data/.svn/props/help.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/help.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/history.right.svn-work b/test/data/.svn/props/history.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/history.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/info-thread.cmd.svn-work b/test/data/.svn/props/info-thread.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/info-thread.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/info-thread.right.svn-work b/test/data/.svn/props/info-thread.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/info-thread.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/info-var-bug2.cmd.svn-work b/test/data/.svn/props/info-var-bug2.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/info-var-bug2.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/info-var-bug2.right.svn-work b/test/data/.svn/props/info-var-bug2.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/info-var-bug2.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/info-var.cmd.svn-work b/test/data/.svn/props/info-var.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/info-var.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/info-var.right.svn-work b/test/data/.svn/props/info-var.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/info-var.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/info.cmd.svn-work b/test/data/.svn/props/info.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/info.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/info.right.svn-work b/test/data/.svn/props/info.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/info.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/linetrace.cmd.svn-work b/test/data/.svn/props/linetrace.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/linetrace.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/linetrace.right.svn-work b/test/data/.svn/props/linetrace.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/linetrace.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/linetracep.cmd.svn-work b/test/data/.svn/props/linetracep.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/linetracep.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/linetracep.right.svn-work b/test/data/.svn/props/linetracep.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/linetracep.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/list.cmd.svn-work b/test/data/.svn/props/list.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/list.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/list.right.svn-work b/test/data/.svn/props/list.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/list.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/method.cmd.svn-work b/test/data/.svn/props/method.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/method.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/method.right.svn-work b/test/data/.svn/props/method.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/method.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/methodsig.cmd.svn-work b/test/data/.svn/props/methodsig.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/methodsig.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/methodsig.right.svn-work b/test/data/.svn/props/methodsig.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/methodsig.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/noquit.right.svn-work b/test/data/.svn/props/noquit.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/noquit.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/output.cmd.svn-work b/test/data/.svn/props/output.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/output.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/output.right.svn-work b/test/data/.svn/props/output.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/output.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/pm-bug.cmd.svn-work b/test/data/.svn/props/pm-bug.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/pm-bug.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/pm-bug.right.svn-work b/test/data/.svn/props/pm-bug.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/pm-bug.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/post-mortem-next.cmd.svn-work b/test/data/.svn/props/post-mortem-next.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/post-mortem-next.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/post-mortem-next.right.svn-work b/test/data/.svn/props/post-mortem-next.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/post-mortem-next.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/post-mortem-osx.right.svn-work b/test/data/.svn/props/post-mortem-osx.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/post-mortem-osx.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/post-mortem.cmd.svn-work b/test/data/.svn/props/post-mortem.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/post-mortem.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/post-mortem.right.svn-work b/test/data/.svn/props/post-mortem.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/post-mortem.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/quit.cmd.svn-work b/test/data/.svn/props/quit.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/quit.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/quit.right.svn-work b/test/data/.svn/props/quit.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/quit.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/raise.cmd.svn-work b/test/data/.svn/props/raise.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/raise.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/raise.right.svn-work b/test/data/.svn/props/raise.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/raise.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/save.cmd.svn-work b/test/data/.svn/props/save.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/save.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/save.right.svn-work b/test/data/.svn/props/save.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/save.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/setshow.cmd.svn-work b/test/data/.svn/props/setshow.cmd.svn-work new file mode 100644 index 0000000..92c8ad7 --- /dev/null +++ b/test/data/.svn/props/setshow.cmd.svn-work @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 2 +Id +END diff --git a/test/data/.svn/props/setshow.right.svn-work b/test/data/.svn/props/setshow.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/setshow.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/source.cmd.svn-work b/test/data/.svn/props/source.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/source.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/source.right.svn-work b/test/data/.svn/props/source.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/source.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/stepping.cmd.svn-work b/test/data/.svn/props/stepping.cmd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/stepping.cmd.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/stepping.right.svn-work b/test/data/.svn/props/stepping.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/stepping.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/test-init-cygwin.right.svn-work b/test/data/.svn/props/test-init-cygwin.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/test-init-cygwin.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/test-init-osx.right.svn-work b/test/data/.svn/props/test-init-osx.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/test-init-osx.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/test-init.right.svn-work b/test/data/.svn/props/test-init.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/test-init.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/props/trace.right.svn-work b/test/data/.svn/props/trace.right.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/test/data/.svn/props/trace.right.svn-work @@ -0,0 +1 @@ +END diff --git a/test/data/.svn/text-base/annotate.cmd.svn-base b/test/data/.svn/text-base/annotate.cmd.svn-base new file mode 100644 index 0000000..1fd55f8 --- /dev/null +++ b/test/data/.svn/text-base/annotate.cmd.svn-base @@ -0,0 +1,29 @@ +# ******************************************************** +# This tests annotations +# ******************************************************** +set debuggertesting on +set callstyle last +set force off +set annotate 3 +# Get into gcd +step 2 +# "break" should trigger break annotation +break 10 +# "delete" should trigger break annotation +delete 1 +# p should not trigger a breakpoint annotation +p a +# "up" should trigger annotations +up +# "b" should trigger like "break" +b 12 +# "display" should trigger display annotation +display 1+2 +# undisplay should trigger display annotation +undisplay 1 +step +# Test error annotations +up 10 +frame 100 +break bogus:5 +quit! diff --git a/test/data/.svn/text-base/annotate.right.svn-base b/test/data/.svn/text-base/annotate.right.svn-base new file mode 100644 index 0000000..9048aff --- /dev/null +++ b/test/data/.svn/text-base/annotate.right.svn-base @@ -0,0 +1,139 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests annotations +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set force off +force-stepping is off. +# set annotate 3 +Annotation level is 3 +# # Get into gcd +# step 2 +starting +stopped +breakpoints +No breakpoints. + +stack +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 + +variables +a = 3 +b = 5 +self = main + +source gcd.rb:6 +if a > b +# # "break" should trigger break annotation +# break 10 +Breakpoint 1 file ./gcd.rb, line 10 +breakpoints +Num Enb What + 1 y at ./gcd.rb:10 + +# # "delete" should trigger break annotation +# delete 1 +breakpoints +No breakpoints. + +# # p should not trigger a breakpoint annotation +# p a +3 +# # "up" should trigger annotations +# up +#1 at line gcd.rb:18 +stack + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 + +variables +self = main + +# # "b" should trigger like "break" +# b 12 +Breakpoint 2 file ./gcd.rb, line 12 +breakpoints +Num Enb What + 2 y at ./gcd.rb:12 + +# # "display" should trigger display annotation +# display 1+2 +1: 1+2 = 3 +display +1: 1+2 = 3 + +# # undisplay should trigger display annotation +# undisplay 1 +display + +# step +display + +starting +stopped +breakpoints +Num Enb What + 2 y at ./gcd.rb:12 + +display + +stack +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 + +variables +a = 3 +b = 5 +self = main + +source gcd.rb:6 +if a > b +# # Test error annotations +# up 10 +error-begin +Adjusting would put us beyond the oldest (initial) frame. + +display + +stack +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 + +variables +a = 3 +b = 5 +self = main + +# frame 100 +error-begin +Adjusting would put us beyond the oldest (initial) frame. + +display + +stack +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 + +variables +a = 3 +b = 5 +self = main + +# break bogus:5 +error-begin +No source file named bogus + +Breakpoint 3 file bogus, line 5 +breakpoints +Num Enb What + 2 y at ./gcd.rb:12 + 3 y at bogus:5 + +display + +# quit! diff --git a/test/data/.svn/text-base/break_bad.cmd.svn-base b/test/data/.svn/text-base/break_bad.cmd.svn-base new file mode 100644 index 0000000..98f17fe --- /dev/null +++ b/test/data/.svn/text-base/break_bad.cmd.svn-base @@ -0,0 +1,18 @@ +# ******************************************************** +# This tests mostly invalid breakpoints. +# We have some valid ones too. +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +# There aren't 100 lines in gcd.rb. +break 100 +break gcd.rb:100 +# Line one isn't a valid stopping point. +# It is a comment. +break gcd.rb:1 +# This line is okay +break gcd.rb:4 +# No class Foo. +break Foo.bar +q diff --git a/test/data/.svn/text-base/break_bad.right.svn-base b/test/data/.svn/text-base/break_bad.right.svn-base new file mode 100644 index 0000000..d27f581 --- /dev/null +++ b/test/data/.svn/text-base/break_bad.right.svn-base @@ -0,0 +1,28 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests mostly invalid breakpoints. +# # We have some valid ones too. +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# # There aren't 100 lines in gcd.rb. +# break 100 +*** There are only 18 lines in file "gcd.rb". +# break gcd.rb:100 +*** There are only 18 lines in file "gcd.rb". +# # Line one isn't a valid stopping point. +# # It is a comment. +# break gcd.rb:1 +*** Line 1 is not a stopping point in file "gcd.rb". +# # This line is okay +# break gcd.rb:4 +Breakpoint 1 file gcd.rb, line 4 +# # No class Foo. +# break Foo.bar +*** Unknown class Foo. +# q diff --git a/test/data/.svn/text-base/break_loop_bug.cmd.svn-base b/test/data/.svn/text-base/break_loop_bug.cmd.svn-base new file mode 100644 index 0000000..cbcb79f --- /dev/null +++ b/test/data/.svn/text-base/break_loop_bug.cmd.svn-base @@ -0,0 +1,5 @@ +set debuggertesting on +break 2 +cont +cont +cont diff --git a/test/data/.svn/text-base/break_loop_bug.right.svn-base b/test/data/.svn/text-base/break_loop_bug.right.svn-base new file mode 100644 index 0000000..4de6124 --- /dev/null +++ b/test/data/.svn/text-base/break_loop_bug.right.svn-base @@ -0,0 +1,15 @@ +bp_loop_issue.rb:1 +1.upto(2) { +# set debuggertesting on +Currently testing the debugger is on. +# break 2 +Breakpoint 1 file ./bp_loop_issue.rb, line 2 +# cont +Breakpoint 1 at bp_loop_issue.rb:2 +bp_loop_issue.rb:2 +sleep 0.01 +# cont +Breakpoint 1 at bp_loop_issue.rb:2 +bp_loop_issue.rb:2 +sleep 0.01 +# cont diff --git a/test/data/.svn/text-base/breakpoints.cmd.svn-base b/test/data/.svn/text-base/breakpoints.cmd.svn-base new file mode 100644 index 0000000..f5d0ff0 --- /dev/null +++ b/test/data/.svn/text-base/breakpoints.cmd.svn-base @@ -0,0 +1,38 @@ +# ******************************************************** +# This tests step, next, continue, disable and +# enable. +# FIXME: break out enable/disable +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break 6 +break 10 +break 11 +continue +where +break Object.gcd +info break +continue +where +info program +c 6 +info break +break foo +info break +disable 1 +info break +delete 1 +# We should see breakpoint 2 but not 1 +info break +# We should still be able to access 2 +disable 2 +disable bar +disable +# We should be able to delete 2 +delete 2 3 +info break +# Should get a message about having no breakpoints. +disable 1 +enable 1 +q! diff --git a/test/data/.svn/text-base/breakpoints.right.svn-base b/test/data/.svn/text-base/breakpoints.right.svn-base new file mode 100644 index 0000000..ef9646b --- /dev/null +++ b/test/data/.svn/text-base/breakpoints.right.svn-base @@ -0,0 +1,98 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests step, next, continue, disable and +# # enable. +# # FIXME: break out enable/disable +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break 6 +Breakpoint 1 file ./gcd.rb, line 6 +# break 10 +Breakpoint 2 file ./gcd.rb, line 10 +# break 11 +*** Line 11 is not a stopping point in file "gcd.rb". +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# break Object.gcd +Breakpoint 3 at Object::gcd +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + 3 y at Object:gcd +# continue +Breakpoint 2 at gcd.rb:10 +gcd.rb:10 +return nil if a <= 0 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:10 + #1 at line gcd.rb:18 +# info program +Program stopped. It stopped at a breakpoint. +# c 6 +Breakpoint 3 at Object:gcd +gcd.rb:4 +def gcd(a, b) +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# break foo +*** Invalid breakpoint location: foo. +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# disable 1 +# info break +Num Enb What + 1 n at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# delete 1 +# # We should see breakpoint 2 but not 1 +# info break +Num Enb What + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# # We should still be able to access 2 +# disable 2 +# disable bar +Disable breakpoints argument 'bar' needs to be a number. +# disable +*** "disable" must be followed "display", "breakpoints" or breakpoint numbers. +# # We should be able to delete 2 +# delete 2 3 +# info break +No breakpoints. +# # Should get a message about having no breakpoints. +# disable 1 +*** No breakpoints have been set. +# enable 1 +*** No breakpoints have been set. +# q! diff --git a/test/data/.svn/text-base/catch.cmd.svn-base b/test/data/.svn/text-base/catch.cmd.svn-base new file mode 100644 index 0000000..0c5eefe --- /dev/null +++ b/test/data/.svn/text-base/catch.cmd.svn-base @@ -0,0 +1,17 @@ +# *************************************************** +# Test catch +# *************************************************** +set debuggertesting on +set autoeval off +set basename on +info catch +catch ZeroDivisionError off +catch ZeroDivisionError off afdasdf +catch ZeroDivisionError +info catch +catch ZeroDivisionError off +info catch +catch ZeroDivisionError +c +where +quit diff --git a/test/data/.svn/text-base/catch.right.svn-base b/test/data/.svn/text-base/catch.right.svn-base new file mode 100644 index 0000000..ec93c02 --- /dev/null +++ b/test/data/.svn/text-base/catch.right.svn-base @@ -0,0 +1,37 @@ +pm.rb:3 +def zero_div +# # *************************************************** +# # Test catch +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set autoeval off +autoeval is off. +# set basename on +basename is on. +# info catch +No exceptions set to be caught. +# catch ZeroDivisionError off +*** Catch for exception ZeroDivisionError not found. +# catch ZeroDivisionError off afdasdf +*** Unknown command: "catch ZeroDivisionError off afdasdf". Try "help". +# catch ZeroDivisionError +Catch exception ZeroDivisionError. +# info catch +ZeroDivisionError +# catch ZeroDivisionError off +Catch for exception ZeroDivisionError removed. +# info catch +No exceptions set to be caught. +# catch ZeroDivisionError +Catch exception ZeroDivisionError. +# c +Catchpoint at pm.rb:5: `divided by 0' (ZeroDivisionError) + from ../rdbg.rb:23:in `runner' + from ../rdbg.rb:32 +pm.rb:5 +1/0 +# where +--> #0 Object./ at line pm.rb:5 + #1 at line pm.rb:8 +# quit diff --git a/test/data/.svn/text-base/condition.cmd.svn-base b/test/data/.svn/text-base/condition.cmd.svn-base new file mode 100644 index 0000000..a2e8967 --- /dev/null +++ b/test/data/.svn/text-base/condition.cmd.svn-base @@ -0,0 +1,28 @@ +# ******************************************************** +# This tests primarily the condition command. +# In order to do this we need to run break, and disable +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break 6 if a > b +info break +condition 1 +info break +break 12 +condition 2 1 == a +# FIXME: should be able to catch error on: +# condition 2 if 1 == a +disable 1 +continue +info break +p a +# Now test trying to enable an invalid breakpoint +break 6 if a > +info break +enable 3 +info break +condition 3 a > 5 +enable 3 +info break +quit diff --git a/test/data/.svn/text-base/condition.right.svn-base b/test/data/.svn/text-base/condition.right.svn-base new file mode 100644 index 0000000..6b9d7b3 --- /dev/null +++ b/test/data/.svn/text-base/condition.right.svn-base @@ -0,0 +1,65 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests primarily the condition command. +# # In order to do this we need to run break, and disable +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break 6 if a > b +Breakpoint 1 file ./gcd.rb, line 6 +# info break +Num Enb What + 1 y at gcd.rb:6 if a > b +# condition 1 +# info break +Num Enb What + 1 y at gcd.rb:6 +# break 12 +Breakpoint 2 file ./gcd.rb, line 12 +# condition 2 1 == a +# # FIXME: should be able to catch error on: +# # condition 2 if 1 == a +# disable 1 +# continue +Breakpoint 2 at gcd.rb:12 +gcd.rb:12 +if a == 1 or b-a == 0 +# info break +Num Enb What + 1 n at gcd.rb:6 + 2 y at gcd.rb:12 if 1 == a + breakpoint already hit 1 time +# p a +1 +# # Now test trying to enable an invalid breakpoint +# break 6 if a > +Breakpoint 3 file ./gcd.rb, line 6 +*** Expression "a > " syntactically incorrect; breakpoint disabled. +# info break +Num Enb What + 1 n at gcd.rb:6 + 2 y at gcd.rb:12 if 1 == a + breakpoint already hit 1 time + 3 n at gcd.rb:6 if a > +# enable 3 +*** Expression "a > " syntactically incorrect; breakpoint remains disabled. +# info break +Num Enb What + 1 n at gcd.rb:6 + 2 y at gcd.rb:12 if 1 == a + breakpoint already hit 1 time + 3 n at gcd.rb:6 if a > +# condition 3 a > 5 +# enable 3 +# info break +Num Enb What + 1 n at gcd.rb:6 + 2 y at gcd.rb:12 if 1 == a + breakpoint already hit 1 time + 3 y at gcd.rb:6 if a > 5 +# quit diff --git a/test/data/.svn/text-base/ctrl.cmd.svn-base b/test/data/.svn/text-base/ctrl.cmd.svn-base new file mode 100644 index 0000000..29b35fd --- /dev/null +++ b/test/data/.svn/text-base/ctrl.cmd.svn-base @@ -0,0 +1,23 @@ +set debuggertesting on +set width 80 +help +help info +info args +info breakpoints +info display +info program +info global_variables +info line +info locals +info stack +info threads +info variables +eval 1+2 +help show +set trace off +show trace +set trace on +set annotate 0 +show annotate + + diff --git a/test/data/.svn/text-base/ctrl.right.svn-base b/test/data/.svn/text-base/ctrl.right.svn-base new file mode 100644 index 0000000..f0aeeb5 --- /dev/null +++ b/test/data/.svn/text-base/ctrl.right.svn-base @@ -0,0 +1,69 @@ +Currently testing the debugger is on. +width is 80. +Type 'help ' for help on a specific command + +Available commands: +break delete eval help interrupt p ps quit restart set source +catch edit exit info kill pp putl reload save show thread + +Generic command for showing things about the program being debugged. +-- +List of info subcommands: +-- +info args -- Argument variables of current stack frame +info breakpoints -- Status of user-settable breakpoints +info catch -- Exceptions that can be caught in the current stack frame +info display -- Expressions to display when program stops +info file -- Info about a particular file read in +info files -- File names and timestamps of files read in +info global_variables -- Global variables +info instance_variables -- Instance variables of the current stack frame +info line -- Line number and file name of current position in source file +info locals -- Local variables of the current stack frame +info program -- Execution status of the program +info stack -- Backtrace of the stack +info thread -- List info about thread NUM +info threads -- information of currently-known threads +info variables -- Local and instance variables of the current stack frame +No frame selected. +info breakpoints not available here. +info display not available here. +The program being debugged is not being run. +info global_variables not available here. +info line not available here. +info line not available here. +info stack not available here. +info threads not available here. +info variables not available here. +3 +Generic command for showing things about the debugger. + +-- +List of show subcommands: +-- +show annotate -- Show annotation level +show args -- Show argument list to give program being debugged when it is started +show autoeval -- Show if unrecognized command are evaluated +show autolist -- Show if 'list' commands is run on breakpoints +show autoirb -- Show if IRB is invoked on debugger stops +show autoreload -- Show if source code is reloaded when changed +show basename -- Show if basename used in reporting files +show callstyle -- Show paramater style used showing call frames +show commands -- Show the history of commands you typed +show forcestep -- Show if sure 'next/step' forces move to a new line +show fullpath -- Show if full file names are displayed in frames +show history -- Generic command for showing command history parameters +show keep-frame-bindings -- Save frame binding on each call +show linetrace -- Show line execution tracing +show linetrace+ -- Show if consecutive lines should be different are shown in tracing +show listsize -- Show number of source lines to list by default +show port -- Show server port +show post-mortem -- Show whether we go into post-mortem debugging on an uncaught exception +show trace -- Show if a stack trace is displayed when 'eval' raises exception +show version -- Show what version of the debugger this is +show width -- Show the number of characters the debugger thinks are in a line +Displaying stack trace is off. +Displaying stack trace is off. +Displaying stack trace is on. +Annotation level is 0 +Annotation level is 0 diff --git a/test/data/.svn/text-base/display.cmd.svn-base b/test/data/.svn/text-base/display.cmd.svn-base new file mode 100644 index 0000000..429c9f1 --- /dev/null +++ b/test/data/.svn/text-base/display.cmd.svn-base @@ -0,0 +1,24 @@ +# *************************************************** +# This tests display expressions. +# *************************************************** +set debuggertesting on +b 6 +c +# Should be no display expression yet. +info display +display a +display b +disable display b +disable display 1 +c +enable display b +enable display 1 +undisplay a +undisplay 2 +# Should have only one display expression. +info display +undisplay 1 +# Now we have no more display expressions. +info display +q + diff --git a/test/data/.svn/text-base/display.right.svn-base b/test/data/.svn/text-base/display.right.svn-base new file mode 100644 index 0000000..7a3b230 --- /dev/null +++ b/test/data/.svn/text-base/display.right.svn-base @@ -0,0 +1,44 @@ +gcd.rb:4 +def gcd(a, b) +# # *************************************************** +# # This tests display expressions. +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# b 6 +Breakpoint 1 file ./gcd.rb, line 6 +# c +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# # Should be no display expression yet. +# info display +There are no auto-display expressions now. +# display a +1: a = 3 +# display b +2: b = 5 +# disable display b +Disable display argument 'b' needs to be a number. +# disable display 1 +# c +Breakpoint 1 at gcd.rb:6 +2: b = 3 +gcd.rb:6 +if a > b +# enable display b +Enable display argument 'b' needs to be a number. +# enable display 1 +# undisplay a +Undisplay argument 'a' needs to be a number. +# undisplay 2 +# # Should have only one display expression. +# info display +Auto-display expressions now in effect: +Num Enb Expression + 1: y a +# undisplay 1 +# # Now we have no more display expressions. +# info display +There are no auto-display expressions now. +# q diff --git a/test/data/.svn/text-base/dollar-0.right.svn-base b/test/data/.svn/text-base/dollar-0.right.svn-base new file mode 100644 index 0000000..b168a38 --- /dev/null +++ b/test/data/.svn/text-base/dollar-0.right.svn-base @@ -0,0 +1,2 @@ +./dollar-0.rb +./dollar-0.rb diff --git a/test/data/.svn/text-base/dollar-0a.right.svn-base b/test/data/.svn/text-base/dollar-0a.right.svn-base new file mode 100644 index 0000000..b168a38 --- /dev/null +++ b/test/data/.svn/text-base/dollar-0a.right.svn-base @@ -0,0 +1,2 @@ +./dollar-0.rb +./dollar-0.rb diff --git a/test/data/.svn/text-base/dollar-0b.right.svn-base b/test/data/.svn/text-base/dollar-0b.right.svn-base new file mode 100644 index 0000000..538a360 --- /dev/null +++ b/test/data/.svn/text-base/dollar-0b.right.svn-base @@ -0,0 +1,2 @@ +../test/dollar-0.rb +../test/dollar-0.rb diff --git a/test/data/.svn/text-base/edit.cmd.svn-base b/test/data/.svn/text-base/edit.cmd.svn-base new file mode 100644 index 0000000..ec4a350 --- /dev/null +++ b/test/data/.svn/text-base/edit.cmd.svn-base @@ -0,0 +1,12 @@ +# ******************************************************** +# This tests the edit command +# ******************************************************** +set debuggertesting on +# Edit using current line position. +edit +edit gcd.rb:5 +# File should not exist +edit foo +# Add space to the end of 'edit' +edit +quit diff --git a/test/data/.svn/text-base/edit.right.svn-base b/test/data/.svn/text-base/edit.right.svn-base new file mode 100644 index 0000000..66523c1 --- /dev/null +++ b/test/data/.svn/text-base/edit.right.svn-base @@ -0,0 +1,19 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the edit command +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# # Edit using current line position. +# edit +FAKE-EDITOR +4 ./gcd.rb +# edit gcd.rb:5 +FAKE-EDITOR +5 gcd.rb +# # File should not exist +# edit foo +*** Invalid file/line number specification: foo +# # Add space to the end of 'edit' +# edit +FAKE-EDITOR +4 ./gcd.rb +# quit diff --git a/test/data/.svn/text-base/emacs_basic.cmd.svn-base b/test/data/.svn/text-base/emacs_basic.cmd.svn-base new file mode 100644 index 0000000..315eb2a --- /dev/null +++ b/test/data/.svn/text-base/emacs_basic.cmd.svn-base @@ -0,0 +1,43 @@ +# ******************************************************** +# This tests step, next, finish, continue, disable and +# enable. +# FIXME: break out enable/disable +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break 6 +break 10 +continue +where +break Foo.bar +break Object.gcd +info break +continue +where +info program +c 10 +info break +break foo +info break +disable 1 +info break +enable breakpoint 1 +enable br 10 +delete 1 +# We should see breakpoint 2 but not 1 +info break +# We should still be able to access 2 +disable 2 +enable +enable foo +disable bar +disable +# We should be able to delete 2 +delete 2 3 +info break +# Should get a message about having no breakpoints. +disable 1 +enable 1 +# finish +quit diff --git a/test/data/.svn/text-base/emacs_basic.right.svn-base b/test/data/.svn/text-base/emacs_basic.right.svn-base new file mode 100644 index 0000000..6d80e2a --- /dev/null +++ b/test/data/.svn/text-base/emacs_basic.right.svn-base @@ -0,0 +1,106 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests step, next, finish, continue, disable and +# # enable. +# # FIXME: break out enable/disable +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break 6 +Breakpoint 1 file ./gcd.rb, line 6 +# break 10 +Breakpoint 2 file ./gcd.rb, line 10 +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# break Foo.bar +*** Unknown class Foo. +# break Object.gcd +Breakpoint 3 at Object::gcd +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + 3 y at Object:gcd +# continue +Breakpoint 2 at gcd.rb:10 +gcd.rb:10 +return nil if a <= 0 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:10 + #1 at line gcd.rb:18 +# info program +Program stopped. It stopped at a breakpoint. +# c 10 +Breakpoint 3 at Object:gcd +gcd.rb:4 +def gcd(a, b) +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# break foo +*** Invalid breakpoint location: foo. +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# disable 1 +# info break +Num Enb What + 1 n at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# enable breakpoint 1 +# enable br 10 +Enable breakpoints argument '10' needs to at most 3. +# delete 1 +# # We should see breakpoint 2 but not 1 +# info break +Num Enb What + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# # We should still be able to access 2 +# disable 2 +# enable +*** "enable" must be followed "display", "breakpoints" or breakpoint numbers. +# enable foo +Enable breakpoints argument 'foo' needs to be a number. +# disable bar +Disable breakpoints argument 'bar' needs to be a number. +# disable +*** "disable" must be followed "display", "breakpoints" or breakpoint numbers. +# # We should be able to delete 2 +# delete 2 3 +# info break +No breakpoints. +# # Should get a message about having no breakpoints. +# disable 1 +*** No breakpoints have been set. +# enable 1 +*** No breakpoints have been set. +# # finish +# quit diff --git a/test/data/.svn/text-base/enable.cmd.svn-base b/test/data/.svn/text-base/enable.cmd.svn-base new file mode 100644 index 0000000..0067f29 --- /dev/null +++ b/test/data/.svn/text-base/enable.cmd.svn-base @@ -0,0 +1,20 @@ +# ******************************************************** +# This tests the enable command. +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break Object.gcd +# Should have a breakpoint 1 +enable br 1 +# Get help on enable +help enable +# Get help on just enable break +help enable break +# Plain enable should work +enable +# An invalid enable command +enable foo +quit + + diff --git a/test/data/.svn/text-base/enable.right.svn-base b/test/data/.svn/text-base/enable.right.svn-base new file mode 100644 index 0000000..ad97ab0 --- /dev/null +++ b/test/data/.svn/text-base/enable.right.svn-base @@ -0,0 +1,36 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the enable command. +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break Object.gcd +Breakpoint 1 at Object::gcd +# # Should have a breakpoint 1 +# enable br 1 +# # Get help on enable +# help enable +Enable some things. +This is used to cancel the effect of the "disable" command. +-- +List of enable subcommands: +-- +enable breakpoints -- Enable specified breakpoints +enable display -- Enable some expressions to be displayed when program stops +# # Get help on just enable break +# help enable break +Enable specified breakpoints. +Give breakpoint numbers (separated by spaces) as arguments. +This is used to cancel the effect of the "disable" command. +# # Plain enable should work +# enable +*** "enable" must be followed "display", "breakpoints" or breakpoint numbers. +# # An invalid enable command +# enable foo +Enable breakpoints argument 'foo' needs to be a number. +# quit diff --git a/test/data/.svn/text-base/finish.cmd.svn-base b/test/data/.svn/text-base/finish.cmd.svn-base new file mode 100644 index 0000000..e10d12b --- /dev/null +++ b/test/data/.svn/text-base/finish.cmd.svn-base @@ -0,0 +1,16 @@ +# ******************************************************** +# This tests finish. +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break 6 +continue +continue +continue +where +finish 0 +where +p a +p b +finish diff --git a/test/data/.svn/text-base/finish.right.svn-base b/test/data/.svn/text-base/finish.right.svn-base new file mode 100644 index 0000000..9979fb0 --- /dev/null +++ b/test/data/.svn/text-base/finish.right.svn-base @@ -0,0 +1,31 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests finish. +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break 6 +Breakpoint 1 file ./gcd.rb, line 6 +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 Object.-(a#Fixnum, b#Fixnum) at line gcd.rb:15 + #2 Object.-(a#Fixnum, b#Fixnum) at line gcd.rb:15 + #3 at line gcd.rb:18 +# finish 0 diff --git a/test/data/.svn/text-base/frame.cmd.svn-base b/test/data/.svn/text-base/frame.cmd.svn-base new file mode 100644 index 0000000..579bc3f --- /dev/null +++ b/test/data/.svn/text-base/frame.cmd.svn-base @@ -0,0 +1,26 @@ +# *************************************************** +# This tests step, next, finish and continue +# *************************************************** +set debuggertesting on +set callstyle last +# Invalid line number in continue command +continue 3 +# This time, for sure! +continue 6 +where +up +where +down +where +frame +where +frame -1 +where +up 2 +where +down 2 +where +frame 0 thread 3 +frame 0 thread 1 +# finish +quit diff --git a/test/data/.svn/text-base/frame.right.svn-base b/test/data/.svn/text-base/frame.right.svn-base new file mode 100644 index 0000000..22b24e6 --- /dev/null +++ b/test/data/.svn/text-base/frame.right.svn-base @@ -0,0 +1,55 @@ +gcd.rb:4 +def gcd(a, b) +# # *************************************************** +# # This tests step, next, finish and continue +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# # Invalid line number in continue command +# continue 3 +*** Line 3 is not a stopping point in file "gcd.rb". +# # This time, for sure! +# continue 6 +gcd.rb:6 +if a > b +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# up +#1 at line gcd.rb:18 +# where + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 +# down +#0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# frame +#0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# frame -1 +#1 at line gcd.rb:18 +# where + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 +# up 2 +*** Adjusting would put us beyond the oldest (initial) frame. +# where + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 +# down 2 +*** Adjusting would put us beyond the newest (innermost) frame. +# where + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 +# frame 0 thread 3 +*** Thread 3 doesn't exist. +# frame 0 thread 1 +#0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +# # finish +# quit diff --git a/test/data/.svn/text-base/help.cmd.svn-base b/test/data/.svn/text-base/help.cmd.svn-base new file mode 100644 index 0000000..4b4dc58 --- /dev/null +++ b/test/data/.svn/text-base/help.cmd.svn-base @@ -0,0 +1,20 @@ +# $Id: setshow.cmd 298 2007-08-28 10:07:35Z rockyb $ +# This tests the functioning of some set/show debugger commands +set debuggertesting on +set autoeval off +set width 80 +### ******************************* +### *** help commands *** +### ******************************* +help foo +help set listsize +help show anno +help show foo +help info file +help info file all +help info file br +help info files + +# FIXME - the below should work +# help +# help step diff --git a/test/data/.svn/text-base/help.right.svn-base b/test/data/.svn/text-base/help.right.svn-base new file mode 100644 index 0000000..52b52ec --- /dev/null +++ b/test/data/.svn/text-base/help.right.svn-base @@ -0,0 +1,21 @@ +Currently testing the debugger is on. +autoeval is off. +width is 80. +Undefined command: "foo". Try "help". +Set number of source lines to list by default. +Show annotation level. +0 == normal; 2 == output annotated suitably for use by programs that control +ruby-debug. +Invalid 'show' subcommand 'foo'. +Info about a particular file read in. + +After the file name is supplied, you can list file attributes that +you wish to see. + +Attributes include: "all", "basic", "breakpoint", "lines", "mtime", "path" +and "sha1". +Info about a particular file read in. +All file information available - breakpoints, lines, mtime, path, and sha1. +Info about a particular file read in. +Show trace line numbers. +File names and timestamps of files read in. diff --git a/test/data/.svn/text-base/history.right.svn-base b/test/data/.svn/text-base/history.right.svn-base new file mode 100644 index 0000000..be1e37f --- /dev/null +++ b/test/data/.svn/text-base/history.right.svn-base @@ -0,0 +1,7 @@ +list +step +show args +show commands +set history save on +show history +quit unconditionally diff --git a/test/data/.svn/text-base/info-thread.cmd.svn-base b/test/data/.svn/text-base/info-thread.cmd.svn-base new file mode 100644 index 0000000..c07064b --- /dev/null +++ b/test/data/.svn/text-base/info-thread.cmd.svn-base @@ -0,0 +1,13 @@ +# ******************************************************** +# This tests basic info thread commands +set debuggertesting on +set callstyle last +set autoeval off +info threads terse +info threads ver +info thread 1 t +info threads +info thread +help info thread +help info threads +q diff --git a/test/data/.svn/text-base/info-thread.right.svn-base b/test/data/.svn/text-base/info-thread.right.svn-base new file mode 100644 index 0000000..fd885bb --- /dev/null +++ b/test/data/.svn/text-base/info-thread.right.svn-base @@ -0,0 +1,37 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests basic info thread commands +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# info threads terse ++ 1 # ./gcd.rb:4 +# info threads ver ++ 1 # + #0 at line gcd.rb:4 +# info thread 1 t ++ 1 # ./gcd.rb:4 +# info threads ++ 1 # ./gcd.rb:4 +# info thread ++ 1 # ./gcd.rb:4 +# help info thread +List info about thread NUM. + +If no thread number is given, we list info for all threads. 'terse' and 'verbose' +options are possible. If terse, just give summary thread name information. See +"help info threads" for more detail about this summary information. + +If 'verbose' appended to the end of the command, then the entire +stack trace is given for each thread. +# help info threads +information of currently-known threads. + +This information includes whether the thread is current (+), if it is +suspended ($), or ignored (!). The thread number and the top stack +item. If 'verbose' is given then the entire stack frame is shown. +# q diff --git a/test/data/.svn/text-base/info-var-bug2.cmd.svn-base b/test/data/.svn/text-base/info-var-bug2.cmd.svn-base new file mode 100644 index 0000000..a8bf887 --- /dev/null +++ b/test/data/.svn/text-base/info-var-bug2.cmd.svn-base @@ -0,0 +1,5 @@ +step +info variables +quit + + diff --git a/test/data/.svn/text-base/info-var-bug2.right.svn-base b/test/data/.svn/text-base/info-var-bug2.right.svn-base new file mode 100644 index 0000000..1b8cdc6 --- /dev/null +++ b/test/data/.svn/text-base/info-var-bug2.right.svn-base @@ -0,0 +1,10 @@ +info-var-bug2.rb:1 +s = '<%= PRODUCT[:name] %>' +# step +info-var-bug2.rb:2 +y = 0 +# info variables +s = "<%= PRODUCT[:name] %>" +self = main +y = nil +# quit diff --git a/test/data/.svn/text-base/info-var.cmd.svn-base b/test/data/.svn/text-base/info-var.cmd.svn-base new file mode 100644 index 0000000..de35cdb --- /dev/null +++ b/test/data/.svn/text-base/info-var.cmd.svn-base @@ -0,0 +1,23 @@ +# *************************************************** +# Test handling of info variables when we have +# redefined inspect or to_s which give an error. +# *************************************************** +set debuggertesting on +# Go to where we have a bad "inspect" of a local variable +continue 36 +info variables +# Go to where we have a bad "inspect" and "to_s" of a local variable +continue 40 +info variables +break 31 +# The first time through, we can do inspect. +continue +info locals +# Now go to where we have a bad "inspect" of an class variable +continue +info locals +info variables +# Now go to where we have a bad "inspect" and "to_s" of an class variable +continue +info locals +quit diff --git a/test/data/.svn/text-base/info-var.right.svn-base b/test/data/.svn/text-base/info-var.right.svn-base new file mode 100644 index 0000000..72c97b3 --- /dev/null +++ b/test/data/.svn/text-base/info-var.right.svn-base @@ -0,0 +1,52 @@ +info-var-bug.rb:1 +class Lousy_inspect +# # *************************************************** +# # Test handling of info variables when we have +# # redefined inspect or to_s which give an error. +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# # Go to where we have a bad "inspect" of a local variable +# continue 36 +info-var-bug.rb:36 +return x +# info variables +self = main +x = # +# # Go to where we have a bad "inspect" and "to_s" of a local variable +# continue 40 +info-var-bug.rb:40 +return x +# info variables +self = main +x = *Error in evaluation* +# break 31 +Breakpoint 1 file ./info-var-bug.rb, line 31 +# # The first time through, we can do inspect. +# continue +Breakpoint 1 at info-var-bug.rb:31 +info-var-bug.rb:31 +@b = 5 +# info locals +a = 10 +# # Now go to where we have a bad "inspect" of an class variable +# continue +Breakpoint 1 at info-var-bug.rb:31 +info-var-bug.rb:31 +@b = 5 +# info locals +a = # +# info variables +a = # +self = # +@a = # +@@Const = "A constant" +@@var = "a class variable" +# # Now go to where we have a bad "inspect" and "to_s" of an class variable +# continue +Breakpoint 1 at info-var-bug.rb:31 +info-var-bug.rb:31 +@b = 5 +# info locals +*Error in evaluation* +# quit diff --git a/test/data/.svn/text-base/info.cmd.svn-base b/test/data/.svn/text-base/info.cmd.svn-base new file mode 100644 index 0000000..d0c2c4a --- /dev/null +++ b/test/data/.svn/text-base/info.cmd.svn-base @@ -0,0 +1,21 @@ +# *************************************************** +# This tests info command handling +# *************************************************** +set debuggertesting on +set callstyle last +help info +info args +info line +info locals +info stack +info display +help info break +help info display +break 10 +break 12 +info break 10 +info break 1 +info break 1 2 +info break +info file ./gcd.rb break +quit diff --git a/test/data/.svn/text-base/info.right.svn-base b/test/data/.svn/text-base/info.right.svn-base new file mode 100644 index 0000000..67ff19e --- /dev/null +++ b/test/data/.svn/text-base/info.right.svn-base @@ -0,0 +1,65 @@ +gcd.rb:4 +def gcd(a, b) +# # *************************************************** +# # This tests info command handling +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# help info +Generic command for showing things about the program being debugged. +-- +List of info subcommands: +-- +info args -- Argument variables of current stack frame +info breakpoints -- Status of user-settable breakpoints +info catch -- Exceptions that can be caught in the current stack frame +info display -- Expressions to display when program stops +info file -- Info about a particular file read in +info files -- File names and timestamps of files read in +info global_variables -- Global variables +info instance_variables -- Instance variables of the current stack frame +info line -- Line number and file name of current position in source file +info locals -- Local variables of the current stack frame +info program -- Execution status of the program +info stack -- Backtrace of the stack +info thread -- List info about thread NUM +info threads -- information of currently-known threads +info variables -- Local and instance variables of the current stack frame +# info args +# info line +Line 4 of "./gcd.rb" +# info locals +# info stack +--> #0 at line gcd.rb:4 +# info display +There are no auto-display expressions now. +# help info break +Status of user-settable breakpoints. +Without argument, list info about all breakpoints. With an +integer argument, list info on that breakpoint. +# help info display +Expressions to display when program stops. +# break 10 +Breakpoint 1 file ./gcd.rb, line 10 +# break 12 +Breakpoint 2 file ./gcd.rb, line 12 +# info break 10 +*** No breakpoints found among list given. +# info break 1 +Num Enb What + 1 y at ./gcd.rb:10 +# info break 1 2 +Num Enb What + 1 y at ./gcd.rb:10 + 2 y at ./gcd.rb:12 +# info break +Num Enb What + 1 y at ./gcd.rb:10 + 2 y at ./gcd.rb:12 +# info file ./gcd.rb break +File ./gcd.rb + breakpoint line numbers: +4 6 6 7 10 10 12 12 13 15 18 +# quit diff --git a/test/data/.svn/text-base/linetrace.cmd.svn-base b/test/data/.svn/text-base/linetrace.cmd.svn-base new file mode 100644 index 0000000..d2424e9 --- /dev/null +++ b/test/data/.svn/text-base/linetrace.cmd.svn-base @@ -0,0 +1,6 @@ +# ******************************************************** +# This tests the 'linetrace' command. +# ******************************************************** +set basename on +set linetrace on +continue diff --git a/test/data/.svn/text-base/linetrace.right.svn-base b/test/data/.svn/text-base/linetrace.right.svn-base new file mode 100644 index 0000000..7aea2cf --- /dev/null +++ b/test/data/.svn/text-base/linetrace.right.svn-base @@ -0,0 +1,32 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the 'linetrace' command. +# # ******************************************************** +# set basename on +basename is on. +# set linetrace on +line tracing is on. +# continue +Tracing(1):gcd.rb:18 gcd(3,5) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:13 return a diff --git a/test/data/.svn/text-base/linetracep.cmd.svn-base b/test/data/.svn/text-base/linetracep.cmd.svn-base new file mode 100644 index 0000000..1d90ec0 --- /dev/null +++ b/test/data/.svn/text-base/linetracep.cmd.svn-base @@ -0,0 +1,7 @@ +# ******************************************************** +# This tests the 'linetrace+' command. +# ******************************************************** +set basename on +set linetrace+ on +set linetrace on +continue diff --git a/test/data/.svn/text-base/linetracep.right.svn-base b/test/data/.svn/text-base/linetracep.right.svn-base new file mode 100644 index 0000000..d3a387e --- /dev/null +++ b/test/data/.svn/text-base/linetracep.right.svn-base @@ -0,0 +1,25 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the 'linetrace+' command. +# # ******************************************************** +# set basename on +basename is on. +# set linetrace+ on +line tracing style is different consecutive lines. +# set linetrace on +line tracing is on. +# continue +Tracing(1):gcd.rb:18 gcd(3,5) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:13 return a diff --git a/test/data/.svn/text-base/list.cmd.svn-base b/test/data/.svn/text-base/list.cmd.svn-base new file mode 100644 index 0000000..a4efa3a --- /dev/null +++ b/test/data/.svn/text-base/list.cmd.svn-base @@ -0,0 +1,19 @@ +# ******************************************************** +# This tests the 'list' command. +# ******************************************************** +set basename on +list +list +list +list +list - +list - +list - +list - +list 1 +list 20 +set listsize 5 +list 5 +list = +list 3-4 + diff --git a/test/data/.svn/text-base/list.right.svn-base b/test/data/.svn/text-base/list.right.svn-base new file mode 100644 index 0000000..cc12084 --- /dev/null +++ b/test/data/.svn/text-base/list.right.svn-base @@ -0,0 +1,127 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the 'list' command. +# # ******************************************************** +# set basename on +basename is on. +# list +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list +[9, 18] in ./gcd.rb + 9 + 10 return nil if a <= 0 + 11 + 12 if a == 1 or b-a == 0 + 13 return a + 14 end + 15 return gcd(b-a, a) + 16 end + 17 + 18 gcd(3,5) +# list +[9, 18] in ./gcd.rb + 9 + 10 return nil if a <= 0 + 11 + 12 if a == 1 or b-a == 0 + 13 return a + 14 end + 15 return gcd(b-a, a) + 16 end + 17 + 18 gcd(3,5) +# list +[9, 18] in ./gcd.rb + 9 + 10 return nil if a <= 0 + 11 + 12 if a == 1 or b-a == 0 + 13 return a + 14 end + 15 return gcd(b-a, a) + 16 end + 17 + 18 gcd(3,5) +# list - +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list - +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list - +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list - +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list 1 +[-4, 5] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b +# list 20 +[15, 24] in ./gcd.rb + 15 return gcd(b-a, a) + 16 end + 17 + 18 gcd(3,5) +# set listsize 5 +Number of source lines to list by default is 5. +# list 5 +[3, 7] in ./gcd.rb + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] +# list = +[2, 6] in ./gcd.rb + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b +# list 3-4 +[3, 4] in ./gcd.rb + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) +# diff --git a/test/data/.svn/text-base/method.cmd.svn-base b/test/data/.svn/text-base/method.cmd.svn-base new file mode 100644 index 0000000..2e9feb8 --- /dev/null +++ b/test/data/.svn/text-base/method.cmd.svn-base @@ -0,0 +1,10 @@ +# ******************************************************** +# This tests the 'method' command +# ******************************************************** +set debuggertesting on +set autoeval off +b 11 +c +method Mine +m iv me +quit diff --git a/test/data/.svn/text-base/method.right.svn-base b/test/data/.svn/text-base/method.right.svn-base new file mode 100644 index 0000000..343bab8 --- /dev/null +++ b/test/data/.svn/text-base/method.right.svn-base @@ -0,0 +1,21 @@ +classes.rb:1 +class Mine +# # ******************************************************** +# # This tests the 'method' command +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set autoeval off +autoeval is off. +# b 11 +Breakpoint 1 file ./classes.rb, line 11 +# c +Breakpoint 1 at classes.rb:11 +classes.rb:11 +metoo = Mine(new) +# method Mine +mymethod + +# m iv me +@myvar = "init" +# quit diff --git a/test/data/.svn/text-base/methodsig.cmd.svn-base b/test/data/.svn/text-base/methodsig.cmd.svn-base new file mode 100644 index 0000000..e3445a8 --- /dev/null +++ b/test/data/.svn/text-base/methodsig.cmd.svn-base @@ -0,0 +1,10 @@ +# ******************************************************** +# This tests the 'method' command +# ******************************************************** +set debuggertesting on +set autoeval off +b 3 +c +method sig initialize +method sig mymethod +quit diff --git a/test/data/.svn/text-base/methodsig.right.svn-base b/test/data/.svn/text-base/methodsig.right.svn-base new file mode 100644 index 0000000..5553b57 --- /dev/null +++ b/test/data/.svn/text-base/methodsig.right.svn-base @@ -0,0 +1,20 @@ +classes.rb:1 +class Mine +# # ******************************************************** +# # This tests the 'method' command +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set autoeval off +autoeval is off. +# b 3 +Breakpoint 1 file ./classes.rb, line 3 +# c +Breakpoint 1 at classes.rb:3 +classes.rb:3 +@myvar = 'init' +# method sig initialize +Mine#initialize() +# method sig mymethod +Mine#mymethod(a, b=5, &block) +# quit diff --git a/test/data/.svn/text-base/noquit.right.svn-base b/test/data/.svn/text-base/noquit.right.svn-base new file mode 100644 index 0000000..b56a50c --- /dev/null +++ b/test/data/.svn/text-base/noquit.right.svn-base @@ -0,0 +1 @@ +The program has finished and will be restarted. diff --git a/test/data/.svn/text-base/output.cmd.svn-base b/test/data/.svn/text-base/output.cmd.svn-base new file mode 100644 index 0000000..1c17bde --- /dev/null +++ b/test/data/.svn/text-base/output.cmd.svn-base @@ -0,0 +1,6 @@ +# ******************************************************** +# This tests the "starting" annotation +# ******************************************************** +step +step +quit diff --git a/test/data/.svn/text-base/output.right.svn-base b/test/data/.svn/text-base/output.right.svn-base new file mode 100644 index 0000000..b70dbeb --- /dev/null +++ b/test/data/.svn/text-base/output.right.svn-base @@ -0,0 +1,31 @@ +starting +stopped +breakpoints +No breakpoints. + +stack +--> #0 at line output.rb:1 + +variables +self = main + +source output.rb:1 +puts "one" +# # ******************************************************** +# # This tests the "starting" annotation +# # ******************************************************** +# step +starting +one +stopped +stack +--> #0 at line output.rb:2 + +variables +self = main + +source output.rb:2 +puts "two" +# step +starting +two diff --git a/test/data/.svn/text-base/pm-bug.cmd.svn-base b/test/data/.svn/text-base/pm-bug.cmd.svn-base new file mode 100644 index 0000000..45a38a0 --- /dev/null +++ b/test/data/.svn/text-base/pm-bug.cmd.svn-base @@ -0,0 +1,7 @@ +# ******************************************************** +# This tests the edit command +# ******************************************************** +set debuggertesting on +# Tracker #22118 +i v +quit diff --git a/test/data/.svn/text-base/pm-bug.right.svn-base b/test/data/.svn/text-base/pm-bug.right.svn-base new file mode 100644 index 0000000..9ce6385 --- /dev/null +++ b/test/data/.svn/text-base/pm-bug.right.svn-base @@ -0,0 +1,12 @@ +pm-bug.rb:1 +a = 1 +# # ******************************************************** +# # This tests the edit command +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# # Tracker #22118 +# i v +a = nil +self = main +# quit diff --git a/test/data/.svn/text-base/post-mortem-next.cmd.svn-base b/test/data/.svn/text-base/post-mortem-next.cmd.svn-base new file mode 100644 index 0000000..09663c9 --- /dev/null +++ b/test/data/.svn/text-base/post-mortem-next.cmd.svn-base @@ -0,0 +1,8 @@ +# ****************************************************** +# This tests running "next" over code that post-mortems +# ****************************************************** +set debuggertesting on +next 2 +next +quit + diff --git a/test/data/.svn/text-base/post-mortem-next.right.svn-base b/test/data/.svn/text-base/post-mortem-next.right.svn-base new file mode 100644 index 0000000..0ecb616 --- /dev/null +++ b/test/data/.svn/text-base/post-mortem-next.right.svn-base @@ -0,0 +1,14 @@ +pm.rb:3 +def zero_div +# # ****************************************************** +# # This tests running "next" over code that post-mortems +# # ****************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# next 2 +pm.rb:8 +zero_div +# next +pm.rb:5 +1/0 +# quit diff --git a/test/data/.svn/text-base/post-mortem-osx.right.svn-base b/test/data/.svn/text-base/post-mortem-osx.right.svn-base new file mode 100644 index 0000000..afa520c --- /dev/null +++ b/test/data/.svn/text-base/post-mortem-osx.right.svn-base @@ -0,0 +1,31 @@ +pm.rb:3 +def zero_div +# # *************************************************** +# # This tests post-mortem handling. +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# continue +pm.rb:5 +1/0 +# # Should have got a divide by 0 error +# info program +The program crashed. +Exception: # +# where +--> #0 / at line pm.rb:5 + #1 at line pm.rb:8 +# up +#1 at line pm.rb:8 +# p x +2 +# help +Type 'help ' for help on a specific command + +Available commands: +backtrace delete edit frame list ps restart source undisplay +break disable enable help method putl save thread up +catch display eval info p quit set tmate var +condition down exit irb pp reload show trace where + +# quit diff --git a/test/data/.svn/text-base/post-mortem.cmd.svn-base b/test/data/.svn/text-base/post-mortem.cmd.svn-base new file mode 100644 index 0000000..d89f0f1 --- /dev/null +++ b/test/data/.svn/text-base/post-mortem.cmd.svn-base @@ -0,0 +1,13 @@ +# *************************************************** +# This tests post-mortem handling. +# *************************************************** +set debuggertesting on +continue +# Should have got a divide by 0 error +info program +where +up +p x +help +quit + diff --git a/test/data/.svn/text-base/post-mortem.right.svn-base b/test/data/.svn/text-base/post-mortem.right.svn-base new file mode 100644 index 0000000..d136ee1 --- /dev/null +++ b/test/data/.svn/text-base/post-mortem.right.svn-base @@ -0,0 +1,32 @@ +pm.rb:3 +def zero_div +# # *************************************************** +# # This tests post-mortem handling. +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# continue +pm.rb:5 +1/0 +# # Should have got a divide by 0 error +# info program +The program crashed. +Exception: # +# where +--> #0 / at line pm.rb:5 + #1 at line pm.rb:8 +# up +#1 at line pm.rb:8 +# p x +2 +# help +Type 'help ' for help on a specific command + +Available commands: +backtrace delete enable info p reload source var +break disable eval irb pp restart thread where +catch display exit kill ps save trace +condition down frame list putl set undisplay +continue edit help method quit show up + +# quit diff --git a/test/data/.svn/text-base/quit.cmd.svn-base b/test/data/.svn/text-base/quit.cmd.svn-base new file mode 100644 index 0000000..e2a69b7 --- /dev/null +++ b/test/data/.svn/text-base/quit.cmd.svn-base @@ -0,0 +1,6 @@ +# *************************************************** +# This tests the quit. +# *************************************************** +set debuggertesting on +# FIXME need to test --no-quit. +quit diff --git a/test/data/.svn/text-base/quit.right.svn-base b/test/data/.svn/text-base/quit.right.svn-base new file mode 100644 index 0000000..e69de29 diff --git a/test/data/.svn/text-base/raise.cmd.svn-base b/test/data/.svn/text-base/raise.cmd.svn-base new file mode 100644 index 0000000..ad1eaee --- /dev/null +++ b/test/data/.svn/text-base/raise.cmd.svn-base @@ -0,0 +1,11 @@ +# ******************************************************** +# This tests that the debugger doesn't step into itself +# when the application doesn't terminate the right way. +# ******************************************************** +set debuggertesting on +catch x +catch ZeroDivisionError +info catch +catch 5 +step +quit diff --git a/test/data/.svn/text-base/raise.right.svn-base b/test/data/.svn/text-base/raise.right.svn-base new file mode 100644 index 0000000..6c86c04 --- /dev/null +++ b/test/data/.svn/text-base/raise.right.svn-base @@ -0,0 +1,26 @@ +raise.rb:3 +raise "abc" +# # ******************************************************** +# # This tests that the debugger doesn't step into itself +# # when the application doesn't terminate the right way. +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# catch x +NameError Exception: undefined local variable or method `x' for main:Object +# catch ZeroDivisionError +Catch exception ZeroDivisionError. +# info catch +ZeroDivisionError +# catch 5 +Warning 5 is not known to be a Class +Catch exception 5. +# step + ./raise.rb:3 + ./tdebug.rb:61:in `debug_load' + ./tdebug.rb:61:in `debug_program' + ./tdebug.rb:251 + ../rdbg.rb:23:in `load' + ../rdbg.rb:23:in `runner' + ../rdbg.rb:32 +Uncaught exception: abc diff --git a/test/data/.svn/text-base/save.cmd.svn-base b/test/data/.svn/text-base/save.cmd.svn-base new file mode 100644 index 0000000..69dae60 --- /dev/null +++ b/test/data/.svn/text-base/save.cmd.svn-base @@ -0,0 +1,33 @@ +# This tests the functioning of some set/show debugger commands +set debuggertesting on +### ******************************* +### *** save/source commands *** +### ******************************* +######################################## +### test args and baseneme... +######################################## +set basename off +set autoeval off +# Should have nothing set +info break +info catch +# Should save nothing +save temp +eval File.open("temp").readlines +# Should read in nothing +source temp +info break +# Now try saving something interesting +break 10 +catch RuntimeError +save temp +eval File.open("temp").readlines +# FIXME: The below is broken +## Change parameters above +## catch RuntimeError off +## info catch +##set listsize 55 +source temp +##info break +##info catch +##show listsize diff --git a/test/data/.svn/text-base/save.right.svn-base b/test/data/.svn/text-base/save.right.svn-base new file mode 100644 index 0000000..83599d0 --- /dev/null +++ b/test/data/.svn/text-base/save.right.svn-base @@ -0,0 +1,59 @@ +gcd.rb:4 +def gcd(a, b) +# # This tests the functioning of some set/show debugger commands +# set debuggertesting on +Currently testing the debugger is on. +# ### ******************************* +# ### *** save/source commands *** +# ### ******************************* +# ######################################## +# ### test args and baseneme... +# ######################################## +# set basename off +basename is off. +# set autoeval off +autoeval is off. +# # Should have nothing set +# info break +No breakpoints. +# info catch +No exceptions set to be caught. +# # Should save nothing +# save temp +Saved to 'temp' +# eval File.open("temp").readlines +["set autoeval off\n", "set basename off\n", "set debuggertesting on\n", "set autolist off\n", "set autoirb off\n"] +# # Should read in nothing +# source temp +autoeval is off. +basename is off. +Currently testing the debugger is on. +autolist is off. +autoirb is off. +# info break +No breakpoints. +# # Now try saving something interesting +# break 10 +Breakpoint 1 file ./gcd.rb, line 10 +# catch RuntimeError +Catch exception RuntimeError. +# save temp +Saved to 'temp' +# eval File.open("temp").readlines +["break ./gcd.rb:10\n", "catch RuntimeError\n", "set autoeval off\n", "set basename on\n", "set debuggertesting on\n", "set autolist off\n", "set autoirb off\n"] +# # FIXME: The below is broken +# ## Change parameters above +# ## catch RuntimeError off +# ## info catch +# ##set listsize 55 +# source temp +Breakpoint 2 file gcd.rb, line 10 +Catch exception RuntimeError. +autoeval is off. +basename is on. +Currently testing the debugger is on. +autolist is off. +autoirb is off. +# ##info break +# ##info catch +# ##show listsize diff --git a/test/data/.svn/text-base/setshow.cmd.svn-base b/test/data/.svn/text-base/setshow.cmd.svn-base new file mode 100644 index 0000000..b842821 --- /dev/null +++ b/test/data/.svn/text-base/setshow.cmd.svn-base @@ -0,0 +1,56 @@ +# This tests the functioning of some set/show debugger commands +set debuggertesting on +### ******************************* +### *** Set/show commands *** +### ******************************* +######################################## +### test args and baseneme... +######################################## +set args this is a test +show args +show basename +set basename foo +show base +set basename off +show basename +set basename 0 +show basename +set basename 1 +show basename +######################################## +### test listsize tests... +######################################## +show listsize +show listsi +set listsize abc +set listsize -20 +######################################## +### test linetrace... +######################################## +set linetrace on +show linetrace +set linetrace off +show linetrace +######################################## +### show history +######################################## +set history +set history size 10 +show history size +set history save off +show history save +set history save 1 +show history save +#### Test 'autoeval'... +set autoeval on +puts 'printed via autoeval' +set autoeval off +puts 'autoeval should not run this' +#### Test 'callstyle'... +set callstyle +set callstyle short +set callstyle last +set callstyle tracked +set callstyle foo + + diff --git a/test/data/.svn/text-base/setshow.right.svn-base b/test/data/.svn/text-base/setshow.right.svn-base new file mode 100644 index 0000000..63aca57 --- /dev/null +++ b/test/data/.svn/text-base/setshow.right.svn-base @@ -0,0 +1,97 @@ +gcd.rb:4 +def gcd(a, b) +# # This tests the functioning of some set/show debugger commands +# set debuggertesting on +Currently testing the debugger is on. +# ### ******************************* +# ### *** Set/show commands *** +# ### ******************************* +# ######################################## +# ### test args and baseneme... +# ######################################## +# set args this is a test +Argument list to give program being debugged when it is started is "this is a test". +# show args +Argument list to give program being debugged when it is started is "this is a test". +# show basename +basename is on. +# set basename foo +Expecting 'on', 1, 'off', or 0. Got: foo. +# show base +basename is on. +# set basename off +basename is off. +# show basename +basename is off. +# set basename 0 +basename is off. +# show basename +basename is off. +# set basename 1 +basename is on. +# show basename +basename is on. +# ######################################## +# ### test listsize tests... +# ######################################## +# show listsize +Number of source lines to list by default is 10. +# show listsi +Number of source lines to list by default is 10. +# set listsize abc +Set listsize argument 'abc' needs to be a number. +# set listsize -20 +Set listsize argument '-20' needs to at least 1. +# ######################################## +# ### test linetrace... +# ######################################## +# set linetrace on +line tracing is on. +# show linetrace +line tracing is on. +# set linetrace off +line tracing is off. +# show linetrace +line tracing is off. +# ######################################## +# ### show history +# ######################################## +# set history +Need two parameters for 'set history'; got 0. +# set history size 10 +Debugger history size is 10 +# show history size +Debugger history size is 10 +# set history save off +Saving of history save is off. +# show history save +Saving of history save is off. +# set history save 1 +Saving of history save is on. +# show history save +Saving of history save is on. +# #### Test 'autoeval'... +# set autoeval on +autoeval is on. +# puts 'printed via autoeval' +printed via autoeval +nil +# set autoeval off +autoeval is off. +# puts 'autoeval should not run this' +*** Unknown command: "puts 'autoeval should not run this'". Try "help". +# #### Test 'callstyle'... +# set callstyle +Invalid call style . Should be one of: 'short', 'last', or 'tracked'. +Frame call-display style is last. +# set callstyle short +Frame call-display style is short. +# set callstyle last +Frame call-display style is last. +# set callstyle tracked +Frame call-display style is tracked. +# set callstyle foo +Invalid call style foo. Should be one of: 'short', 'last', or 'tracked'. +Frame call-display style is tracked. +# +# diff --git a/test/data/.svn/text-base/source.cmd.svn-base b/test/data/.svn/text-base/source.cmd.svn-base new file mode 100644 index 0000000..71716f3 --- /dev/null +++ b/test/data/.svn/text-base/source.cmd.svn-base @@ -0,0 +1,5 @@ +# Test the source command +# rdebug-save has breakpoint commands +set debuggertesting on +source ./rdebug-save.1 +quit diff --git a/test/data/.svn/text-base/source.right.svn-base b/test/data/.svn/text-base/source.right.svn-base new file mode 100644 index 0000000..40d0cf8 --- /dev/null +++ b/test/data/.svn/text-base/source.right.svn-base @@ -0,0 +1,15 @@ +gcd.rb:4 +def gcd(a, b) +# # Test the source command +# # rdebug-save has breakpoint commands +# set debuggertesting on +Currently testing the debugger is on. +# source ./rdebug-save.1 +Breakpoint 1 file gcd.rb, line 10 +Breakpoint 2 file gcd.rb, line 12 +autoeval is on. +basename is off. +Currently testing the debugger is on. +autolist is off. +autoirb is off. +# quit diff --git a/test/data/.svn/text-base/stepping.cmd.svn-base b/test/data/.svn/text-base/stepping.cmd.svn-base new file mode 100644 index 0000000..f9a7473 --- /dev/null +++ b/test/data/.svn/text-base/stepping.cmd.svn-base @@ -0,0 +1,21 @@ +# *************************************************** +# This tests step, next, finish and continue +# *************************************************** +set debuggertesting on +set callstyle last +next +where +step a +set forcestep on +step- ; step- +set forcestep off +where +n 2 +step+ +where +step 3 +step+ +where +next+ +# finish +quit diff --git a/test/data/.svn/text-base/stepping.right.svn-base b/test/data/.svn/text-base/stepping.right.svn-base new file mode 100644 index 0000000..7791547 --- /dev/null +++ b/test/data/.svn/text-base/stepping.right.svn-base @@ -0,0 +1,50 @@ +gcd.rb:4 +def gcd(a, b) +# # *************************************************** +# # This tests step, next, finish and continue +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# next +gcd.rb:18 +gcd(3,5) +# where +--> #0 at line gcd.rb:18 +# step a +Step argument 'a' needs to be a number. +# set forcestep on +force-stepping is on. +# step- ; step- +gcd.rb:6 +if a > b +# set forcestep off +force-stepping is off. +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# n 2 +gcd.rb:10 +return nil if a <= 0 +# step+ +gcd.rb:12 +if a == 1 or b-a == 0 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:12 + #1 at line gcd.rb:18 +# step 3 +gcd.rb:6 +if a > b +# step+ +gcd.rb:10 +return nil if a <= 0 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:10 + #1 Object.-(a#Fixnum, b#Fixnum) at line gcd.rb:15 + #2 at line gcd.rb:18 +# next+ +gcd.rb:12 +if a == 1 or b-a == 0 +# # finish +# quit diff --git a/test/data/.svn/text-base/test-init-cygwin.right.svn-base b/test/data/.svn/text-base/test-init-cygwin.right.svn-base new file mode 100644 index 0000000..8d683f3 --- /dev/null +++ b/test/data/.svn/text-base/test-init-cygwin.right.svn-base @@ -0,0 +1,7 @@ +gcd-dbg.rb:18 +if a > b +(rdb:1) p Debugger::PROG_SCRIPT +"./gcd-dbg.rb" +(rdb:1) show args +Argument list to give program being debugged when it is started is "5". +(rdb:1) quit unconditionally diff --git a/test/data/.svn/text-base/test-init-osx.right.svn-base b/test/data/.svn/text-base/test-init-osx.right.svn-base new file mode 100644 index 0000000..a50319c --- /dev/null +++ b/test/data/.svn/text-base/test-init-osx.right.svn-base @@ -0,0 +1,4 @@ +gcd-dbg.rb:18 +if a > b +"./gcd-dbg.rb" +Argument list to give program being debugged when it is started is "5". diff --git a/test/data/.svn/text-base/test-init.right.svn-base b/test/data/.svn/text-base/test-init.right.svn-base new file mode 100644 index 0000000..981c233 --- /dev/null +++ b/test/data/.svn/text-base/test-init.right.svn-base @@ -0,0 +1,5 @@ +gcd-dbg.rb:18 +if a > b +(rdb:1) "./gcd-dbg.rb" +(rdb:1) Argument list to give program being debugged when it is started is "5". +(rdb:1) \ No newline at end of file diff --git a/test/data/.svn/text-base/trace.right.svn-base b/test/data/.svn/text-base/trace.right.svn-base new file mode 100644 index 0000000..ada9008 --- /dev/null +++ b/test/data/.svn/text-base/trace.right.svn-base @@ -0,0 +1,23 @@ +Tracing(1):gcd.rb:4 def gcd(a, b) +Tracing(1):gcd.rb:18 gcd(3,5) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:13 return a diff --git a/test/data/annotate.cmd b/test/data/annotate.cmd new file mode 100644 index 0000000..1fd55f8 --- /dev/null +++ b/test/data/annotate.cmd @@ -0,0 +1,29 @@ +# ******************************************************** +# This tests annotations +# ******************************************************** +set debuggertesting on +set callstyle last +set force off +set annotate 3 +# Get into gcd +step 2 +# "break" should trigger break annotation +break 10 +# "delete" should trigger break annotation +delete 1 +# p should not trigger a breakpoint annotation +p a +# "up" should trigger annotations +up +# "b" should trigger like "break" +b 12 +# "display" should trigger display annotation +display 1+2 +# undisplay should trigger display annotation +undisplay 1 +step +# Test error annotations +up 10 +frame 100 +break bogus:5 +quit! diff --git a/test/data/annotate.right b/test/data/annotate.right new file mode 100644 index 0000000..9048aff --- /dev/null +++ b/test/data/annotate.right @@ -0,0 +1,139 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests annotations +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set force off +force-stepping is off. +# set annotate 3 +Annotation level is 3 +# # Get into gcd +# step 2 +starting +stopped +breakpoints +No breakpoints. + +stack +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 + +variables +a = 3 +b = 5 +self = main + +source gcd.rb:6 +if a > b +# # "break" should trigger break annotation +# break 10 +Breakpoint 1 file ./gcd.rb, line 10 +breakpoints +Num Enb What + 1 y at ./gcd.rb:10 + +# # "delete" should trigger break annotation +# delete 1 +breakpoints +No breakpoints. + +# # p should not trigger a breakpoint annotation +# p a +3 +# # "up" should trigger annotations +# up +#1 at line gcd.rb:18 +stack + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 + +variables +self = main + +# # "b" should trigger like "break" +# b 12 +Breakpoint 2 file ./gcd.rb, line 12 +breakpoints +Num Enb What + 2 y at ./gcd.rb:12 + +# # "display" should trigger display annotation +# display 1+2 +1: 1+2 = 3 +display +1: 1+2 = 3 + +# # undisplay should trigger display annotation +# undisplay 1 +display + +# step +display + +starting +stopped +breakpoints +Num Enb What + 2 y at ./gcd.rb:12 + +display + +stack +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 + +variables +a = 3 +b = 5 +self = main + +source gcd.rb:6 +if a > b +# # Test error annotations +# up 10 +error-begin +Adjusting would put us beyond the oldest (initial) frame. + +display + +stack +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 + +variables +a = 3 +b = 5 +self = main + +# frame 100 +error-begin +Adjusting would put us beyond the oldest (initial) frame. + +display + +stack +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 + +variables +a = 3 +b = 5 +self = main + +# break bogus:5 +error-begin +No source file named bogus + +Breakpoint 3 file bogus, line 5 +breakpoints +Num Enb What + 2 y at ./gcd.rb:12 + 3 y at bogus:5 + +display + +# quit! diff --git a/test/data/break_bad.cmd b/test/data/break_bad.cmd new file mode 100644 index 0000000..98f17fe --- /dev/null +++ b/test/data/break_bad.cmd @@ -0,0 +1,18 @@ +# ******************************************************** +# This tests mostly invalid breakpoints. +# We have some valid ones too. +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +# There aren't 100 lines in gcd.rb. +break 100 +break gcd.rb:100 +# Line one isn't a valid stopping point. +# It is a comment. +break gcd.rb:1 +# This line is okay +break gcd.rb:4 +# No class Foo. +break Foo.bar +q diff --git a/test/data/break_bad.right b/test/data/break_bad.right new file mode 100644 index 0000000..d27f581 --- /dev/null +++ b/test/data/break_bad.right @@ -0,0 +1,28 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests mostly invalid breakpoints. +# # We have some valid ones too. +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# # There aren't 100 lines in gcd.rb. +# break 100 +*** There are only 18 lines in file "gcd.rb". +# break gcd.rb:100 +*** There are only 18 lines in file "gcd.rb". +# # Line one isn't a valid stopping point. +# # It is a comment. +# break gcd.rb:1 +*** Line 1 is not a stopping point in file "gcd.rb". +# # This line is okay +# break gcd.rb:4 +Breakpoint 1 file gcd.rb, line 4 +# # No class Foo. +# break Foo.bar +*** Unknown class Foo. +# q diff --git a/test/data/break_loop_bug.cmd b/test/data/break_loop_bug.cmd new file mode 100644 index 0000000..cbcb79f --- /dev/null +++ b/test/data/break_loop_bug.cmd @@ -0,0 +1,5 @@ +set debuggertesting on +break 2 +cont +cont +cont diff --git a/test/data/break_loop_bug.right b/test/data/break_loop_bug.right new file mode 100644 index 0000000..4de6124 --- /dev/null +++ b/test/data/break_loop_bug.right @@ -0,0 +1,15 @@ +bp_loop_issue.rb:1 +1.upto(2) { +# set debuggertesting on +Currently testing the debugger is on. +# break 2 +Breakpoint 1 file ./bp_loop_issue.rb, line 2 +# cont +Breakpoint 1 at bp_loop_issue.rb:2 +bp_loop_issue.rb:2 +sleep 0.01 +# cont +Breakpoint 1 at bp_loop_issue.rb:2 +bp_loop_issue.rb:2 +sleep 0.01 +# cont diff --git a/test/data/breakpoints.cmd b/test/data/breakpoints.cmd new file mode 100644 index 0000000..f5d0ff0 --- /dev/null +++ b/test/data/breakpoints.cmd @@ -0,0 +1,38 @@ +# ******************************************************** +# This tests step, next, continue, disable and +# enable. +# FIXME: break out enable/disable +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break 6 +break 10 +break 11 +continue +where +break Object.gcd +info break +continue +where +info program +c 6 +info break +break foo +info break +disable 1 +info break +delete 1 +# We should see breakpoint 2 but not 1 +info break +# We should still be able to access 2 +disable 2 +disable bar +disable +# We should be able to delete 2 +delete 2 3 +info break +# Should get a message about having no breakpoints. +disable 1 +enable 1 +q! diff --git a/test/data/breakpoints.right b/test/data/breakpoints.right new file mode 100644 index 0000000..ef9646b --- /dev/null +++ b/test/data/breakpoints.right @@ -0,0 +1,98 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests step, next, continue, disable and +# # enable. +# # FIXME: break out enable/disable +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break 6 +Breakpoint 1 file ./gcd.rb, line 6 +# break 10 +Breakpoint 2 file ./gcd.rb, line 10 +# break 11 +*** Line 11 is not a stopping point in file "gcd.rb". +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# break Object.gcd +Breakpoint 3 at Object::gcd +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + 3 y at Object:gcd +# continue +Breakpoint 2 at gcd.rb:10 +gcd.rb:10 +return nil if a <= 0 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:10 + #1 at line gcd.rb:18 +# info program +Program stopped. It stopped at a breakpoint. +# c 6 +Breakpoint 3 at Object:gcd +gcd.rb:4 +def gcd(a, b) +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# break foo +*** Invalid breakpoint location: foo. +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# disable 1 +# info break +Num Enb What + 1 n at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# delete 1 +# # We should see breakpoint 2 but not 1 +# info break +Num Enb What + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# # We should still be able to access 2 +# disable 2 +# disable bar +Disable breakpoints argument 'bar' needs to be a number. +# disable +*** "disable" must be followed "display", "breakpoints" or breakpoint numbers. +# # We should be able to delete 2 +# delete 2 3 +# info break +No breakpoints. +# # Should get a message about having no breakpoints. +# disable 1 +*** No breakpoints have been set. +# enable 1 +*** No breakpoints have been set. +# q! diff --git a/test/data/catch.cmd b/test/data/catch.cmd new file mode 100644 index 0000000..0c5eefe --- /dev/null +++ b/test/data/catch.cmd @@ -0,0 +1,17 @@ +# *************************************************** +# Test catch +# *************************************************** +set debuggertesting on +set autoeval off +set basename on +info catch +catch ZeroDivisionError off +catch ZeroDivisionError off afdasdf +catch ZeroDivisionError +info catch +catch ZeroDivisionError off +info catch +catch ZeroDivisionError +c +where +quit diff --git a/test/data/catch.right b/test/data/catch.right new file mode 100644 index 0000000..ec93c02 --- /dev/null +++ b/test/data/catch.right @@ -0,0 +1,37 @@ +pm.rb:3 +def zero_div +# # *************************************************** +# # Test catch +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set autoeval off +autoeval is off. +# set basename on +basename is on. +# info catch +No exceptions set to be caught. +# catch ZeroDivisionError off +*** Catch for exception ZeroDivisionError not found. +# catch ZeroDivisionError off afdasdf +*** Unknown command: "catch ZeroDivisionError off afdasdf". Try "help". +# catch ZeroDivisionError +Catch exception ZeroDivisionError. +# info catch +ZeroDivisionError +# catch ZeroDivisionError off +Catch for exception ZeroDivisionError removed. +# info catch +No exceptions set to be caught. +# catch ZeroDivisionError +Catch exception ZeroDivisionError. +# c +Catchpoint at pm.rb:5: `divided by 0' (ZeroDivisionError) + from ../rdbg.rb:23:in `runner' + from ../rdbg.rb:32 +pm.rb:5 +1/0 +# where +--> #0 Object./ at line pm.rb:5 + #1 at line pm.rb:8 +# quit diff --git a/test/data/condition.cmd b/test/data/condition.cmd new file mode 100644 index 0000000..a2e8967 --- /dev/null +++ b/test/data/condition.cmd @@ -0,0 +1,28 @@ +# ******************************************************** +# This tests primarily the condition command. +# In order to do this we need to run break, and disable +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break 6 if a > b +info break +condition 1 +info break +break 12 +condition 2 1 == a +# FIXME: should be able to catch error on: +# condition 2 if 1 == a +disable 1 +continue +info break +p a +# Now test trying to enable an invalid breakpoint +break 6 if a > +info break +enable 3 +info break +condition 3 a > 5 +enable 3 +info break +quit diff --git a/test/data/condition.right b/test/data/condition.right new file mode 100644 index 0000000..6b9d7b3 --- /dev/null +++ b/test/data/condition.right @@ -0,0 +1,65 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests primarily the condition command. +# # In order to do this we need to run break, and disable +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break 6 if a > b +Breakpoint 1 file ./gcd.rb, line 6 +# info break +Num Enb What + 1 y at gcd.rb:6 if a > b +# condition 1 +# info break +Num Enb What + 1 y at gcd.rb:6 +# break 12 +Breakpoint 2 file ./gcd.rb, line 12 +# condition 2 1 == a +# # FIXME: should be able to catch error on: +# # condition 2 if 1 == a +# disable 1 +# continue +Breakpoint 2 at gcd.rb:12 +gcd.rb:12 +if a == 1 or b-a == 0 +# info break +Num Enb What + 1 n at gcd.rb:6 + 2 y at gcd.rb:12 if 1 == a + breakpoint already hit 1 time +# p a +1 +# # Now test trying to enable an invalid breakpoint +# break 6 if a > +Breakpoint 3 file ./gcd.rb, line 6 +*** Expression "a > " syntactically incorrect; breakpoint disabled. +# info break +Num Enb What + 1 n at gcd.rb:6 + 2 y at gcd.rb:12 if 1 == a + breakpoint already hit 1 time + 3 n at gcd.rb:6 if a > +# enable 3 +*** Expression "a > " syntactically incorrect; breakpoint remains disabled. +# info break +Num Enb What + 1 n at gcd.rb:6 + 2 y at gcd.rb:12 if 1 == a + breakpoint already hit 1 time + 3 n at gcd.rb:6 if a > +# condition 3 a > 5 +# enable 3 +# info break +Num Enb What + 1 n at gcd.rb:6 + 2 y at gcd.rb:12 if 1 == a + breakpoint already hit 1 time + 3 y at gcd.rb:6 if a > 5 +# quit diff --git a/test/data/ctrl.cmd b/test/data/ctrl.cmd new file mode 100644 index 0000000..29b35fd --- /dev/null +++ b/test/data/ctrl.cmd @@ -0,0 +1,23 @@ +set debuggertesting on +set width 80 +help +help info +info args +info breakpoints +info display +info program +info global_variables +info line +info locals +info stack +info threads +info variables +eval 1+2 +help show +set trace off +show trace +set trace on +set annotate 0 +show annotate + + diff --git a/test/data/ctrl.right b/test/data/ctrl.right new file mode 100644 index 0000000..f0aeeb5 --- /dev/null +++ b/test/data/ctrl.right @@ -0,0 +1,69 @@ +Currently testing the debugger is on. +width is 80. +Type 'help ' for help on a specific command + +Available commands: +break delete eval help interrupt p ps quit restart set source +catch edit exit info kill pp putl reload save show thread + +Generic command for showing things about the program being debugged. +-- +List of info subcommands: +-- +info args -- Argument variables of current stack frame +info breakpoints -- Status of user-settable breakpoints +info catch -- Exceptions that can be caught in the current stack frame +info display -- Expressions to display when program stops +info file -- Info about a particular file read in +info files -- File names and timestamps of files read in +info global_variables -- Global variables +info instance_variables -- Instance variables of the current stack frame +info line -- Line number and file name of current position in source file +info locals -- Local variables of the current stack frame +info program -- Execution status of the program +info stack -- Backtrace of the stack +info thread -- List info about thread NUM +info threads -- information of currently-known threads +info variables -- Local and instance variables of the current stack frame +No frame selected. +info breakpoints not available here. +info display not available here. +The program being debugged is not being run. +info global_variables not available here. +info line not available here. +info line not available here. +info stack not available here. +info threads not available here. +info variables not available here. +3 +Generic command for showing things about the debugger. + +-- +List of show subcommands: +-- +show annotate -- Show annotation level +show args -- Show argument list to give program being debugged when it is started +show autoeval -- Show if unrecognized command are evaluated +show autolist -- Show if 'list' commands is run on breakpoints +show autoirb -- Show if IRB is invoked on debugger stops +show autoreload -- Show if source code is reloaded when changed +show basename -- Show if basename used in reporting files +show callstyle -- Show paramater style used showing call frames +show commands -- Show the history of commands you typed +show forcestep -- Show if sure 'next/step' forces move to a new line +show fullpath -- Show if full file names are displayed in frames +show history -- Generic command for showing command history parameters +show keep-frame-bindings -- Save frame binding on each call +show linetrace -- Show line execution tracing +show linetrace+ -- Show if consecutive lines should be different are shown in tracing +show listsize -- Show number of source lines to list by default +show port -- Show server port +show post-mortem -- Show whether we go into post-mortem debugging on an uncaught exception +show trace -- Show if a stack trace is displayed when 'eval' raises exception +show version -- Show what version of the debugger this is +show width -- Show the number of characters the debugger thinks are in a line +Displaying stack trace is off. +Displaying stack trace is off. +Displaying stack trace is on. +Annotation level is 0 +Annotation level is 0 diff --git a/test/data/display.cmd b/test/data/display.cmd new file mode 100644 index 0000000..429c9f1 --- /dev/null +++ b/test/data/display.cmd @@ -0,0 +1,24 @@ +# *************************************************** +# This tests display expressions. +# *************************************************** +set debuggertesting on +b 6 +c +# Should be no display expression yet. +info display +display a +display b +disable display b +disable display 1 +c +enable display b +enable display 1 +undisplay a +undisplay 2 +# Should have only one display expression. +info display +undisplay 1 +# Now we have no more display expressions. +info display +q + diff --git a/test/data/display.right b/test/data/display.right new file mode 100644 index 0000000..7a3b230 --- /dev/null +++ b/test/data/display.right @@ -0,0 +1,44 @@ +gcd.rb:4 +def gcd(a, b) +# # *************************************************** +# # This tests display expressions. +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# b 6 +Breakpoint 1 file ./gcd.rb, line 6 +# c +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# # Should be no display expression yet. +# info display +There are no auto-display expressions now. +# display a +1: a = 3 +# display b +2: b = 5 +# disable display b +Disable display argument 'b' needs to be a number. +# disable display 1 +# c +Breakpoint 1 at gcd.rb:6 +2: b = 3 +gcd.rb:6 +if a > b +# enable display b +Enable display argument 'b' needs to be a number. +# enable display 1 +# undisplay a +Undisplay argument 'a' needs to be a number. +# undisplay 2 +# # Should have only one display expression. +# info display +Auto-display expressions now in effect: +Num Enb Expression + 1: y a +# undisplay 1 +# # Now we have no more display expressions. +# info display +There are no auto-display expressions now. +# q diff --git a/test/data/dollar-0.right b/test/data/dollar-0.right new file mode 100644 index 0000000..b168a38 --- /dev/null +++ b/test/data/dollar-0.right @@ -0,0 +1,2 @@ +./dollar-0.rb +./dollar-0.rb diff --git a/test/data/dollar-0a.right b/test/data/dollar-0a.right new file mode 100644 index 0000000..b168a38 --- /dev/null +++ b/test/data/dollar-0a.right @@ -0,0 +1,2 @@ +./dollar-0.rb +./dollar-0.rb diff --git a/test/data/dollar-0b.right b/test/data/dollar-0b.right new file mode 100644 index 0000000..538a360 --- /dev/null +++ b/test/data/dollar-0b.right @@ -0,0 +1,2 @@ +../test/dollar-0.rb +../test/dollar-0.rb diff --git a/test/data/edit.cmd b/test/data/edit.cmd new file mode 100644 index 0000000..ec4a350 --- /dev/null +++ b/test/data/edit.cmd @@ -0,0 +1,12 @@ +# ******************************************************** +# This tests the edit command +# ******************************************************** +set debuggertesting on +# Edit using current line position. +edit +edit gcd.rb:5 +# File should not exist +edit foo +# Add space to the end of 'edit' +edit +quit diff --git a/test/data/edit.right b/test/data/edit.right new file mode 100644 index 0000000..66523c1 --- /dev/null +++ b/test/data/edit.right @@ -0,0 +1,19 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the edit command +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# # Edit using current line position. +# edit +FAKE-EDITOR +4 ./gcd.rb +# edit gcd.rb:5 +FAKE-EDITOR +5 gcd.rb +# # File should not exist +# edit foo +*** Invalid file/line number specification: foo +# # Add space to the end of 'edit' +# edit +FAKE-EDITOR +4 ./gcd.rb +# quit diff --git a/test/data/emacs_basic.cmd b/test/data/emacs_basic.cmd new file mode 100644 index 0000000..315eb2a --- /dev/null +++ b/test/data/emacs_basic.cmd @@ -0,0 +1,43 @@ +# ******************************************************** +# This tests step, next, finish, continue, disable and +# enable. +# FIXME: break out enable/disable +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break 6 +break 10 +continue +where +break Foo.bar +break Object.gcd +info break +continue +where +info program +c 10 +info break +break foo +info break +disable 1 +info break +enable breakpoint 1 +enable br 10 +delete 1 +# We should see breakpoint 2 but not 1 +info break +# We should still be able to access 2 +disable 2 +enable +enable foo +disable bar +disable +# We should be able to delete 2 +delete 2 3 +info break +# Should get a message about having no breakpoints. +disable 1 +enable 1 +# finish +quit diff --git a/test/data/emacs_basic.right b/test/data/emacs_basic.right new file mode 100644 index 0000000..6d80e2a --- /dev/null +++ b/test/data/emacs_basic.right @@ -0,0 +1,106 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests step, next, finish, continue, disable and +# # enable. +# # FIXME: break out enable/disable +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break 6 +Breakpoint 1 file ./gcd.rb, line 6 +# break 10 +Breakpoint 2 file ./gcd.rb, line 10 +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# break Foo.bar +*** Unknown class Foo. +# break Object.gcd +Breakpoint 3 at Object::gcd +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + 3 y at Object:gcd +# continue +Breakpoint 2 at gcd.rb:10 +gcd.rb:10 +return nil if a <= 0 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:10 + #1 at line gcd.rb:18 +# info program +Program stopped. It stopped at a breakpoint. +# c 10 +Breakpoint 3 at Object:gcd +gcd.rb:4 +def gcd(a, b) +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# break foo +*** Invalid breakpoint location: foo. +# info break +Num Enb What + 1 y at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# disable 1 +# info break +Num Enb What + 1 n at ./gcd.rb:6 + breakpoint already hit 1 time + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# enable breakpoint 1 +# enable br 10 +Enable breakpoints argument '10' needs to at most 3. +# delete 1 +# # We should see breakpoint 2 but not 1 +# info break +Num Enb What + 2 y at ./gcd.rb:10 + breakpoint already hit 1 time + 3 y at Object:gcd + breakpoint already hit 1 time +# # We should still be able to access 2 +# disable 2 +# enable +*** "enable" must be followed "display", "breakpoints" or breakpoint numbers. +# enable foo +Enable breakpoints argument 'foo' needs to be a number. +# disable bar +Disable breakpoints argument 'bar' needs to be a number. +# disable +*** "disable" must be followed "display", "breakpoints" or breakpoint numbers. +# # We should be able to delete 2 +# delete 2 3 +# info break +No breakpoints. +# # Should get a message about having no breakpoints. +# disable 1 +*** No breakpoints have been set. +# enable 1 +*** No breakpoints have been set. +# # finish +# quit diff --git a/test/data/enable.cmd b/test/data/enable.cmd new file mode 100644 index 0000000..0067f29 --- /dev/null +++ b/test/data/enable.cmd @@ -0,0 +1,20 @@ +# ******************************************************** +# This tests the enable command. +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break Object.gcd +# Should have a breakpoint 1 +enable br 1 +# Get help on enable +help enable +# Get help on just enable break +help enable break +# Plain enable should work +enable +# An invalid enable command +enable foo +quit + + diff --git a/test/data/enable.right b/test/data/enable.right new file mode 100644 index 0000000..ad97ab0 --- /dev/null +++ b/test/data/enable.right @@ -0,0 +1,36 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the enable command. +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break Object.gcd +Breakpoint 1 at Object::gcd +# # Should have a breakpoint 1 +# enable br 1 +# # Get help on enable +# help enable +Enable some things. +This is used to cancel the effect of the "disable" command. +-- +List of enable subcommands: +-- +enable breakpoints -- Enable specified breakpoints +enable display -- Enable some expressions to be displayed when program stops +# # Get help on just enable break +# help enable break +Enable specified breakpoints. +Give breakpoint numbers (separated by spaces) as arguments. +This is used to cancel the effect of the "disable" command. +# # Plain enable should work +# enable +*** "enable" must be followed "display", "breakpoints" or breakpoint numbers. +# # An invalid enable command +# enable foo +Enable breakpoints argument 'foo' needs to be a number. +# quit diff --git a/test/data/finish.cmd b/test/data/finish.cmd new file mode 100644 index 0000000..e10d12b --- /dev/null +++ b/test/data/finish.cmd @@ -0,0 +1,16 @@ +# ******************************************************** +# This tests finish. +# ******************************************************** +set debuggertesting on +set callstyle last +set autoeval off +break 6 +continue +continue +continue +where +finish 0 +where +p a +p b +finish diff --git a/test/data/finish.right b/test/data/finish.right new file mode 100644 index 0000000..9979fb0 --- /dev/null +++ b/test/data/finish.right @@ -0,0 +1,31 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests finish. +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# break 6 +Breakpoint 1 file ./gcd.rb, line 6 +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# continue +Breakpoint 1 at gcd.rb:6 +gcd.rb:6 +if a > b +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 Object.-(a#Fixnum, b#Fixnum) at line gcd.rb:15 + #2 Object.-(a#Fixnum, b#Fixnum) at line gcd.rb:15 + #3 at line gcd.rb:18 +# finish 0 diff --git a/test/data/frame.cmd b/test/data/frame.cmd new file mode 100644 index 0000000..579bc3f --- /dev/null +++ b/test/data/frame.cmd @@ -0,0 +1,26 @@ +# *************************************************** +# This tests step, next, finish and continue +# *************************************************** +set debuggertesting on +set callstyle last +# Invalid line number in continue command +continue 3 +# This time, for sure! +continue 6 +where +up +where +down +where +frame +where +frame -1 +where +up 2 +where +down 2 +where +frame 0 thread 3 +frame 0 thread 1 +# finish +quit diff --git a/test/data/frame.right b/test/data/frame.right new file mode 100644 index 0000000..22b24e6 --- /dev/null +++ b/test/data/frame.right @@ -0,0 +1,55 @@ +gcd.rb:4 +def gcd(a, b) +# # *************************************************** +# # This tests step, next, finish and continue +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# # Invalid line number in continue command +# continue 3 +*** Line 3 is not a stopping point in file "gcd.rb". +# # This time, for sure! +# continue 6 +gcd.rb:6 +if a > b +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# up +#1 at line gcd.rb:18 +# where + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 +# down +#0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# frame +#0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# frame -1 +#1 at line gcd.rb:18 +# where + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 +# up 2 +*** Adjusting would put us beyond the oldest (initial) frame. +# where + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 +# down 2 +*** Adjusting would put us beyond the newest (innermost) frame. +# where + #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +--> #1 at line gcd.rb:18 +# frame 0 thread 3 +*** Thread 3 doesn't exist. +# frame 0 thread 1 +#0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 +# # finish +# quit diff --git a/test/data/help.cmd b/test/data/help.cmd new file mode 100644 index 0000000..4b4dc58 --- /dev/null +++ b/test/data/help.cmd @@ -0,0 +1,20 @@ +# $Id: setshow.cmd 298 2007-08-28 10:07:35Z rockyb $ +# This tests the functioning of some set/show debugger commands +set debuggertesting on +set autoeval off +set width 80 +### ******************************* +### *** help commands *** +### ******************************* +help foo +help set listsize +help show anno +help show foo +help info file +help info file all +help info file br +help info files + +# FIXME - the below should work +# help +# help step diff --git a/test/data/help.right b/test/data/help.right new file mode 100644 index 0000000..52b52ec --- /dev/null +++ b/test/data/help.right @@ -0,0 +1,21 @@ +Currently testing the debugger is on. +autoeval is off. +width is 80. +Undefined command: "foo". Try "help". +Set number of source lines to list by default. +Show annotation level. +0 == normal; 2 == output annotated suitably for use by programs that control +ruby-debug. +Invalid 'show' subcommand 'foo'. +Info about a particular file read in. + +After the file name is supplied, you can list file attributes that +you wish to see. + +Attributes include: "all", "basic", "breakpoint", "lines", "mtime", "path" +and "sha1". +Info about a particular file read in. +All file information available - breakpoints, lines, mtime, path, and sha1. +Info about a particular file read in. +Show trace line numbers. +File names and timestamps of files read in. diff --git a/test/data/history.right b/test/data/history.right new file mode 100644 index 0000000..be1e37f --- /dev/null +++ b/test/data/history.right @@ -0,0 +1,7 @@ +list +step +show args +show commands +set history save on +show history +quit unconditionally diff --git a/test/data/info-thread.cmd b/test/data/info-thread.cmd new file mode 100644 index 0000000..c07064b --- /dev/null +++ b/test/data/info-thread.cmd @@ -0,0 +1,13 @@ +# ******************************************************** +# This tests basic info thread commands +set debuggertesting on +set callstyle last +set autoeval off +info threads terse +info threads ver +info thread 1 t +info threads +info thread +help info thread +help info threads +q diff --git a/test/data/info-thread.right b/test/data/info-thread.right new file mode 100644 index 0000000..fd885bb --- /dev/null +++ b/test/data/info-thread.right @@ -0,0 +1,37 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests basic info thread commands +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# set autoeval off +autoeval is off. +# info threads terse ++ 1 # ./gcd.rb:4 +# info threads ver ++ 1 # + #0 at line gcd.rb:4 +# info thread 1 t ++ 1 # ./gcd.rb:4 +# info threads ++ 1 # ./gcd.rb:4 +# info thread ++ 1 # ./gcd.rb:4 +# help info thread +List info about thread NUM. + +If no thread number is given, we list info for all threads. 'terse' and 'verbose' +options are possible. If terse, just give summary thread name information. See +"help info threads" for more detail about this summary information. + +If 'verbose' appended to the end of the command, then the entire +stack trace is given for each thread. +# help info threads +information of currently-known threads. + +This information includes whether the thread is current (+), if it is +suspended ($), or ignored (!). The thread number and the top stack +item. If 'verbose' is given then the entire stack frame is shown. +# q diff --git a/test/data/info-var-bug2.cmd b/test/data/info-var-bug2.cmd new file mode 100644 index 0000000..a8bf887 --- /dev/null +++ b/test/data/info-var-bug2.cmd @@ -0,0 +1,5 @@ +step +info variables +quit + + diff --git a/test/data/info-var-bug2.right b/test/data/info-var-bug2.right new file mode 100644 index 0000000..1b8cdc6 --- /dev/null +++ b/test/data/info-var-bug2.right @@ -0,0 +1,10 @@ +info-var-bug2.rb:1 +s = '<%= PRODUCT[:name] %>' +# step +info-var-bug2.rb:2 +y = 0 +# info variables +s = "<%= PRODUCT[:name] %>" +self = main +y = nil +# quit diff --git a/test/data/info-var.cmd b/test/data/info-var.cmd new file mode 100644 index 0000000..de35cdb --- /dev/null +++ b/test/data/info-var.cmd @@ -0,0 +1,23 @@ +# *************************************************** +# Test handling of info variables when we have +# redefined inspect or to_s which give an error. +# *************************************************** +set debuggertesting on +# Go to where we have a bad "inspect" of a local variable +continue 36 +info variables +# Go to where we have a bad "inspect" and "to_s" of a local variable +continue 40 +info variables +break 31 +# The first time through, we can do inspect. +continue +info locals +# Now go to where we have a bad "inspect" of an class variable +continue +info locals +info variables +# Now go to where we have a bad "inspect" and "to_s" of an class variable +continue +info locals +quit diff --git a/test/data/info-var.right b/test/data/info-var.right new file mode 100644 index 0000000..72c97b3 --- /dev/null +++ b/test/data/info-var.right @@ -0,0 +1,52 @@ +info-var-bug.rb:1 +class Lousy_inspect +# # *************************************************** +# # Test handling of info variables when we have +# # redefined inspect or to_s which give an error. +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# # Go to where we have a bad "inspect" of a local variable +# continue 36 +info-var-bug.rb:36 +return x +# info variables +self = main +x = # +# # Go to where we have a bad "inspect" and "to_s" of a local variable +# continue 40 +info-var-bug.rb:40 +return x +# info variables +self = main +x = *Error in evaluation* +# break 31 +Breakpoint 1 file ./info-var-bug.rb, line 31 +# # The first time through, we can do inspect. +# continue +Breakpoint 1 at info-var-bug.rb:31 +info-var-bug.rb:31 +@b = 5 +# info locals +a = 10 +# # Now go to where we have a bad "inspect" of an class variable +# continue +Breakpoint 1 at info-var-bug.rb:31 +info-var-bug.rb:31 +@b = 5 +# info locals +a = # +# info variables +a = # +self = # +@a = # +@@Const = "A constant" +@@var = "a class variable" +# # Now go to where we have a bad "inspect" and "to_s" of an class variable +# continue +Breakpoint 1 at info-var-bug.rb:31 +info-var-bug.rb:31 +@b = 5 +# info locals +*Error in evaluation* +# quit diff --git a/test/data/info.cmd b/test/data/info.cmd new file mode 100644 index 0000000..d0c2c4a --- /dev/null +++ b/test/data/info.cmd @@ -0,0 +1,21 @@ +# *************************************************** +# This tests info command handling +# *************************************************** +set debuggertesting on +set callstyle last +help info +info args +info line +info locals +info stack +info display +help info break +help info display +break 10 +break 12 +info break 10 +info break 1 +info break 1 2 +info break +info file ./gcd.rb break +quit diff --git a/test/data/info.right b/test/data/info.right new file mode 100644 index 0000000..67ff19e --- /dev/null +++ b/test/data/info.right @@ -0,0 +1,65 @@ +gcd.rb:4 +def gcd(a, b) +# # *************************************************** +# # This tests info command handling +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# help info +Generic command for showing things about the program being debugged. +-- +List of info subcommands: +-- +info args -- Argument variables of current stack frame +info breakpoints -- Status of user-settable breakpoints +info catch -- Exceptions that can be caught in the current stack frame +info display -- Expressions to display when program stops +info file -- Info about a particular file read in +info files -- File names and timestamps of files read in +info global_variables -- Global variables +info instance_variables -- Instance variables of the current stack frame +info line -- Line number and file name of current position in source file +info locals -- Local variables of the current stack frame +info program -- Execution status of the program +info stack -- Backtrace of the stack +info thread -- List info about thread NUM +info threads -- information of currently-known threads +info variables -- Local and instance variables of the current stack frame +# info args +# info line +Line 4 of "./gcd.rb" +# info locals +# info stack +--> #0 at line gcd.rb:4 +# info display +There are no auto-display expressions now. +# help info break +Status of user-settable breakpoints. +Without argument, list info about all breakpoints. With an +integer argument, list info on that breakpoint. +# help info display +Expressions to display when program stops. +# break 10 +Breakpoint 1 file ./gcd.rb, line 10 +# break 12 +Breakpoint 2 file ./gcd.rb, line 12 +# info break 10 +*** No breakpoints found among list given. +# info break 1 +Num Enb What + 1 y at ./gcd.rb:10 +# info break 1 2 +Num Enb What + 1 y at ./gcd.rb:10 + 2 y at ./gcd.rb:12 +# info break +Num Enb What + 1 y at ./gcd.rb:10 + 2 y at ./gcd.rb:12 +# info file ./gcd.rb break +File ./gcd.rb + breakpoint line numbers: +4 6 6 7 10 10 12 12 13 15 18 +# quit diff --git a/test/data/linetrace.cmd b/test/data/linetrace.cmd new file mode 100644 index 0000000..d2424e9 --- /dev/null +++ b/test/data/linetrace.cmd @@ -0,0 +1,6 @@ +# ******************************************************** +# This tests the 'linetrace' command. +# ******************************************************** +set basename on +set linetrace on +continue diff --git a/test/data/linetrace.right b/test/data/linetrace.right new file mode 100644 index 0000000..7aea2cf --- /dev/null +++ b/test/data/linetrace.right @@ -0,0 +1,32 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the 'linetrace' command. +# # ******************************************************** +# set basename on +basename is on. +# set linetrace on +line tracing is on. +# continue +Tracing(1):gcd.rb:18 gcd(3,5) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:13 return a diff --git a/test/data/linetracep.cmd b/test/data/linetracep.cmd new file mode 100644 index 0000000..1d90ec0 --- /dev/null +++ b/test/data/linetracep.cmd @@ -0,0 +1,7 @@ +# ******************************************************** +# This tests the 'linetrace+' command. +# ******************************************************** +set basename on +set linetrace+ on +set linetrace on +continue diff --git a/test/data/linetracep.right b/test/data/linetracep.right new file mode 100644 index 0000000..d3a387e --- /dev/null +++ b/test/data/linetracep.right @@ -0,0 +1,25 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the 'linetrace+' command. +# # ******************************************************** +# set basename on +basename is on. +# set linetrace+ on +line tracing style is different consecutive lines. +# set linetrace on +line tracing is on. +# continue +Tracing(1):gcd.rb:18 gcd(3,5) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:13 return a diff --git a/test/data/list.cmd b/test/data/list.cmd new file mode 100644 index 0000000..a4efa3a --- /dev/null +++ b/test/data/list.cmd @@ -0,0 +1,19 @@ +# ******************************************************** +# This tests the 'list' command. +# ******************************************************** +set basename on +list +list +list +list +list - +list - +list - +list - +list 1 +list 20 +set listsize 5 +list 5 +list = +list 3-4 + diff --git a/test/data/list.right b/test/data/list.right new file mode 100644 index 0000000..cc12084 --- /dev/null +++ b/test/data/list.right @@ -0,0 +1,127 @@ +gcd.rb:4 +def gcd(a, b) +# # ******************************************************** +# # This tests the 'list' command. +# # ******************************************************** +# set basename on +basename is on. +# list +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list +[9, 18] in ./gcd.rb + 9 + 10 return nil if a <= 0 + 11 + 12 if a == 1 or b-a == 0 + 13 return a + 14 end + 15 return gcd(b-a, a) + 16 end + 17 + 18 gcd(3,5) +# list +[9, 18] in ./gcd.rb + 9 + 10 return nil if a <= 0 + 11 + 12 if a == 1 or b-a == 0 + 13 return a + 14 end + 15 return gcd(b-a, a) + 16 end + 17 + 18 gcd(3,5) +# list +[9, 18] in ./gcd.rb + 9 + 10 return nil if a <= 0 + 11 + 12 if a == 1 or b-a == 0 + 13 return a + 14 end + 15 return gcd(b-a, a) + 16 end + 17 + 18 gcd(3,5) +# list - +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list - +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list - +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list - +[-1, 8] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] + 8 end +# list 1 +[-4, 5] in ./gcd.rb + 1 #!/usr/bin/env ruby + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b +# list 20 +[15, 24] in ./gcd.rb + 15 return gcd(b-a, a) + 16 end + 17 + 18 gcd(3,5) +# set listsize 5 +Number of source lines to list by default is 5. +# list 5 +[3, 7] in ./gcd.rb + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b + 7 a, b = [b, a] +# list = +[2, 6] in ./gcd.rb + 2 + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) + 5 # Make: a <= b + 6 if a > b +# list 3-4 +[3, 4] in ./gcd.rb + 3 # GCD. We assume positive numbers +=> 4 def gcd(a, b) +# diff --git a/test/data/method.cmd b/test/data/method.cmd new file mode 100644 index 0000000..2e9feb8 --- /dev/null +++ b/test/data/method.cmd @@ -0,0 +1,10 @@ +# ******************************************************** +# This tests the 'method' command +# ******************************************************** +set debuggertesting on +set autoeval off +b 11 +c +method Mine +m iv me +quit diff --git a/test/data/method.right b/test/data/method.right new file mode 100644 index 0000000..343bab8 --- /dev/null +++ b/test/data/method.right @@ -0,0 +1,21 @@ +classes.rb:1 +class Mine +# # ******************************************************** +# # This tests the 'method' command +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set autoeval off +autoeval is off. +# b 11 +Breakpoint 1 file ./classes.rb, line 11 +# c +Breakpoint 1 at classes.rb:11 +classes.rb:11 +metoo = Mine(new) +# method Mine +mymethod + +# m iv me +@myvar = "init" +# quit diff --git a/test/data/methodsig.cmd b/test/data/methodsig.cmd new file mode 100644 index 0000000..e3445a8 --- /dev/null +++ b/test/data/methodsig.cmd @@ -0,0 +1,10 @@ +# ******************************************************** +# This tests the 'method' command +# ******************************************************** +set debuggertesting on +set autoeval off +b 3 +c +method sig initialize +method sig mymethod +quit diff --git a/test/data/methodsig.right b/test/data/methodsig.right new file mode 100644 index 0000000..5553b57 --- /dev/null +++ b/test/data/methodsig.right @@ -0,0 +1,20 @@ +classes.rb:1 +class Mine +# # ******************************************************** +# # This tests the 'method' command +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set autoeval off +autoeval is off. +# b 3 +Breakpoint 1 file ./classes.rb, line 3 +# c +Breakpoint 1 at classes.rb:3 +classes.rb:3 +@myvar = 'init' +# method sig initialize +Mine#initialize() +# method sig mymethod +Mine#mymethod(a, b=5, &block) +# quit diff --git a/test/data/noquit.right b/test/data/noquit.right new file mode 100644 index 0000000..b56a50c --- /dev/null +++ b/test/data/noquit.right @@ -0,0 +1 @@ +The program has finished and will be restarted. diff --git a/test/data/output.cmd b/test/data/output.cmd new file mode 100644 index 0000000..1c17bde --- /dev/null +++ b/test/data/output.cmd @@ -0,0 +1,6 @@ +# ******************************************************** +# This tests the "starting" annotation +# ******************************************************** +step +step +quit diff --git a/test/data/output.right b/test/data/output.right new file mode 100644 index 0000000..b70dbeb --- /dev/null +++ b/test/data/output.right @@ -0,0 +1,31 @@ +starting +stopped +breakpoints +No breakpoints. + +stack +--> #0 at line output.rb:1 + +variables +self = main + +source output.rb:1 +puts "one" +# # ******************************************************** +# # This tests the "starting" annotation +# # ******************************************************** +# step +starting +one +stopped +stack +--> #0 at line output.rb:2 + +variables +self = main + +source output.rb:2 +puts "two" +# step +starting +two diff --git a/test/data/pm-bug.cmd b/test/data/pm-bug.cmd new file mode 100644 index 0000000..45a38a0 --- /dev/null +++ b/test/data/pm-bug.cmd @@ -0,0 +1,7 @@ +# ******************************************************** +# This tests the edit command +# ******************************************************** +set debuggertesting on +# Tracker #22118 +i v +quit diff --git a/test/data/pm-bug.right b/test/data/pm-bug.right new file mode 100644 index 0000000..9ce6385 --- /dev/null +++ b/test/data/pm-bug.right @@ -0,0 +1,12 @@ +pm-bug.rb:1 +a = 1 +# # ******************************************************** +# # This tests the edit command +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# # Tracker #22118 +# i v +a = nil +self = main +# quit diff --git a/test/data/post-mortem-next.cmd b/test/data/post-mortem-next.cmd new file mode 100644 index 0000000..09663c9 --- /dev/null +++ b/test/data/post-mortem-next.cmd @@ -0,0 +1,8 @@ +# ****************************************************** +# This tests running "next" over code that post-mortems +# ****************************************************** +set debuggertesting on +next 2 +next +quit + diff --git a/test/data/post-mortem-next.right b/test/data/post-mortem-next.right new file mode 100644 index 0000000..0ecb616 --- /dev/null +++ b/test/data/post-mortem-next.right @@ -0,0 +1,14 @@ +pm.rb:3 +def zero_div +# # ****************************************************** +# # This tests running "next" over code that post-mortems +# # ****************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# next 2 +pm.rb:8 +zero_div +# next +pm.rb:5 +1/0 +# quit diff --git a/test/data/post-mortem-osx.right b/test/data/post-mortem-osx.right new file mode 100644 index 0000000..afa520c --- /dev/null +++ b/test/data/post-mortem-osx.right @@ -0,0 +1,31 @@ +pm.rb:3 +def zero_div +# # *************************************************** +# # This tests post-mortem handling. +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# continue +pm.rb:5 +1/0 +# # Should have got a divide by 0 error +# info program +The program crashed. +Exception: # +# where +--> #0 / at line pm.rb:5 + #1 at line pm.rb:8 +# up +#1 at line pm.rb:8 +# p x +2 +# help +Type 'help ' for help on a specific command + +Available commands: +backtrace delete edit frame list ps restart source undisplay +break disable enable help method putl save thread up +catch display eval info p quit set tmate var +condition down exit irb pp reload show trace where + +# quit diff --git a/test/data/post-mortem.cmd b/test/data/post-mortem.cmd new file mode 100644 index 0000000..d89f0f1 --- /dev/null +++ b/test/data/post-mortem.cmd @@ -0,0 +1,13 @@ +# *************************************************** +# This tests post-mortem handling. +# *************************************************** +set debuggertesting on +continue +# Should have got a divide by 0 error +info program +where +up +p x +help +quit + diff --git a/test/data/post-mortem.right b/test/data/post-mortem.right new file mode 100644 index 0000000..d136ee1 --- /dev/null +++ b/test/data/post-mortem.right @@ -0,0 +1,32 @@ +pm.rb:3 +def zero_div +# # *************************************************** +# # This tests post-mortem handling. +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# continue +pm.rb:5 +1/0 +# # Should have got a divide by 0 error +# info program +The program crashed. +Exception: # +# where +--> #0 / at line pm.rb:5 + #1 at line pm.rb:8 +# up +#1 at line pm.rb:8 +# p x +2 +# help +Type 'help ' for help on a specific command + +Available commands: +backtrace delete enable info p reload source var +break disable eval irb pp restart thread where +catch display exit kill ps save trace +condition down frame list putl set undisplay +continue edit help method quit show up + +# quit diff --git a/test/data/quit.cmd b/test/data/quit.cmd new file mode 100644 index 0000000..e2a69b7 --- /dev/null +++ b/test/data/quit.cmd @@ -0,0 +1,6 @@ +# *************************************************** +# This tests the quit. +# *************************************************** +set debuggertesting on +# FIXME need to test --no-quit. +quit diff --git a/test/data/quit.right b/test/data/quit.right new file mode 100644 index 0000000..e69de29 diff --git a/test/data/raise.cmd b/test/data/raise.cmd new file mode 100644 index 0000000..ad1eaee --- /dev/null +++ b/test/data/raise.cmd @@ -0,0 +1,11 @@ +# ******************************************************** +# This tests that the debugger doesn't step into itself +# when the application doesn't terminate the right way. +# ******************************************************** +set debuggertesting on +catch x +catch ZeroDivisionError +info catch +catch 5 +step +quit diff --git a/test/data/raise.right b/test/data/raise.right new file mode 100644 index 0000000..6c86c04 --- /dev/null +++ b/test/data/raise.right @@ -0,0 +1,26 @@ +raise.rb:3 +raise "abc" +# # ******************************************************** +# # This tests that the debugger doesn't step into itself +# # when the application doesn't terminate the right way. +# # ******************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# catch x +NameError Exception: undefined local variable or method `x' for main:Object +# catch ZeroDivisionError +Catch exception ZeroDivisionError. +# info catch +ZeroDivisionError +# catch 5 +Warning 5 is not known to be a Class +Catch exception 5. +# step + ./raise.rb:3 + ./tdebug.rb:61:in `debug_load' + ./tdebug.rb:61:in `debug_program' + ./tdebug.rb:251 + ../rdbg.rb:23:in `load' + ../rdbg.rb:23:in `runner' + ../rdbg.rb:32 +Uncaught exception: abc diff --git a/test/data/save.cmd b/test/data/save.cmd new file mode 100644 index 0000000..69dae60 --- /dev/null +++ b/test/data/save.cmd @@ -0,0 +1,33 @@ +# This tests the functioning of some set/show debugger commands +set debuggertesting on +### ******************************* +### *** save/source commands *** +### ******************************* +######################################## +### test args and baseneme... +######################################## +set basename off +set autoeval off +# Should have nothing set +info break +info catch +# Should save nothing +save temp +eval File.open("temp").readlines +# Should read in nothing +source temp +info break +# Now try saving something interesting +break 10 +catch RuntimeError +save temp +eval File.open("temp").readlines +# FIXME: The below is broken +## Change parameters above +## catch RuntimeError off +## info catch +##set listsize 55 +source temp +##info break +##info catch +##show listsize diff --git a/test/data/save.right b/test/data/save.right new file mode 100644 index 0000000..83599d0 --- /dev/null +++ b/test/data/save.right @@ -0,0 +1,59 @@ +gcd.rb:4 +def gcd(a, b) +# # This tests the functioning of some set/show debugger commands +# set debuggertesting on +Currently testing the debugger is on. +# ### ******************************* +# ### *** save/source commands *** +# ### ******************************* +# ######################################## +# ### test args and baseneme... +# ######################################## +# set basename off +basename is off. +# set autoeval off +autoeval is off. +# # Should have nothing set +# info break +No breakpoints. +# info catch +No exceptions set to be caught. +# # Should save nothing +# save temp +Saved to 'temp' +# eval File.open("temp").readlines +["set autoeval off\n", "set basename off\n", "set debuggertesting on\n", "set autolist off\n", "set autoirb off\n"] +# # Should read in nothing +# source temp +autoeval is off. +basename is off. +Currently testing the debugger is on. +autolist is off. +autoirb is off. +# info break +No breakpoints. +# # Now try saving something interesting +# break 10 +Breakpoint 1 file ./gcd.rb, line 10 +# catch RuntimeError +Catch exception RuntimeError. +# save temp +Saved to 'temp' +# eval File.open("temp").readlines +["break ./gcd.rb:10\n", "catch RuntimeError\n", "set autoeval off\n", "set basename on\n", "set debuggertesting on\n", "set autolist off\n", "set autoirb off\n"] +# # FIXME: The below is broken +# ## Change parameters above +# ## catch RuntimeError off +# ## info catch +# ##set listsize 55 +# source temp +Breakpoint 2 file gcd.rb, line 10 +Catch exception RuntimeError. +autoeval is off. +basename is on. +Currently testing the debugger is on. +autolist is off. +autoirb is off. +# ##info break +# ##info catch +# ##show listsize diff --git a/test/data/setshow.cmd b/test/data/setshow.cmd new file mode 100644 index 0000000..b842821 --- /dev/null +++ b/test/data/setshow.cmd @@ -0,0 +1,56 @@ +# This tests the functioning of some set/show debugger commands +set debuggertesting on +### ******************************* +### *** Set/show commands *** +### ******************************* +######################################## +### test args and baseneme... +######################################## +set args this is a test +show args +show basename +set basename foo +show base +set basename off +show basename +set basename 0 +show basename +set basename 1 +show basename +######################################## +### test listsize tests... +######################################## +show listsize +show listsi +set listsize abc +set listsize -20 +######################################## +### test linetrace... +######################################## +set linetrace on +show linetrace +set linetrace off +show linetrace +######################################## +### show history +######################################## +set history +set history size 10 +show history size +set history save off +show history save +set history save 1 +show history save +#### Test 'autoeval'... +set autoeval on +puts 'printed via autoeval' +set autoeval off +puts 'autoeval should not run this' +#### Test 'callstyle'... +set callstyle +set callstyle short +set callstyle last +set callstyle tracked +set callstyle foo + + diff --git a/test/data/setshow.right b/test/data/setshow.right new file mode 100644 index 0000000..63aca57 --- /dev/null +++ b/test/data/setshow.right @@ -0,0 +1,97 @@ +gcd.rb:4 +def gcd(a, b) +# # This tests the functioning of some set/show debugger commands +# set debuggertesting on +Currently testing the debugger is on. +# ### ******************************* +# ### *** Set/show commands *** +# ### ******************************* +# ######################################## +# ### test args and baseneme... +# ######################################## +# set args this is a test +Argument list to give program being debugged when it is started is "this is a test". +# show args +Argument list to give program being debugged when it is started is "this is a test". +# show basename +basename is on. +# set basename foo +Expecting 'on', 1, 'off', or 0. Got: foo. +# show base +basename is on. +# set basename off +basename is off. +# show basename +basename is off. +# set basename 0 +basename is off. +# show basename +basename is off. +# set basename 1 +basename is on. +# show basename +basename is on. +# ######################################## +# ### test listsize tests... +# ######################################## +# show listsize +Number of source lines to list by default is 10. +# show listsi +Number of source lines to list by default is 10. +# set listsize abc +Set listsize argument 'abc' needs to be a number. +# set listsize -20 +Set listsize argument '-20' needs to at least 1. +# ######################################## +# ### test linetrace... +# ######################################## +# set linetrace on +line tracing is on. +# show linetrace +line tracing is on. +# set linetrace off +line tracing is off. +# show linetrace +line tracing is off. +# ######################################## +# ### show history +# ######################################## +# set history +Need two parameters for 'set history'; got 0. +# set history size 10 +Debugger history size is 10 +# show history size +Debugger history size is 10 +# set history save off +Saving of history save is off. +# show history save +Saving of history save is off. +# set history save 1 +Saving of history save is on. +# show history save +Saving of history save is on. +# #### Test 'autoeval'... +# set autoeval on +autoeval is on. +# puts 'printed via autoeval' +printed via autoeval +nil +# set autoeval off +autoeval is off. +# puts 'autoeval should not run this' +*** Unknown command: "puts 'autoeval should not run this'". Try "help". +# #### Test 'callstyle'... +# set callstyle +Invalid call style . Should be one of: 'short', 'last', or 'tracked'. +Frame call-display style is last. +# set callstyle short +Frame call-display style is short. +# set callstyle last +Frame call-display style is last. +# set callstyle tracked +Frame call-display style is tracked. +# set callstyle foo +Invalid call style foo. Should be one of: 'short', 'last', or 'tracked'. +Frame call-display style is tracked. +# +# diff --git a/test/data/source.cmd b/test/data/source.cmd new file mode 100644 index 0000000..71716f3 --- /dev/null +++ b/test/data/source.cmd @@ -0,0 +1,5 @@ +# Test the source command +# rdebug-save has breakpoint commands +set debuggertesting on +source ./rdebug-save.1 +quit diff --git a/test/data/source.right b/test/data/source.right new file mode 100644 index 0000000..40d0cf8 --- /dev/null +++ b/test/data/source.right @@ -0,0 +1,15 @@ +gcd.rb:4 +def gcd(a, b) +# # Test the source command +# # rdebug-save has breakpoint commands +# set debuggertesting on +Currently testing the debugger is on. +# source ./rdebug-save.1 +Breakpoint 1 file gcd.rb, line 10 +Breakpoint 2 file gcd.rb, line 12 +autoeval is on. +basename is off. +Currently testing the debugger is on. +autolist is off. +autoirb is off. +# quit diff --git a/test/data/stepping.cmd b/test/data/stepping.cmd new file mode 100644 index 0000000..f9a7473 --- /dev/null +++ b/test/data/stepping.cmd @@ -0,0 +1,21 @@ +# *************************************************** +# This tests step, next, finish and continue +# *************************************************** +set debuggertesting on +set callstyle last +next +where +step a +set forcestep on +step- ; step- +set forcestep off +where +n 2 +step+ +where +step 3 +step+ +where +next+ +# finish +quit diff --git a/test/data/stepping.right b/test/data/stepping.right new file mode 100644 index 0000000..7791547 --- /dev/null +++ b/test/data/stepping.right @@ -0,0 +1,50 @@ +gcd.rb:4 +def gcd(a, b) +# # *************************************************** +# # This tests step, next, finish and continue +# # *************************************************** +# set debuggertesting on +Currently testing the debugger is on. +# set callstyle last +Frame call-display style is last. +# next +gcd.rb:18 +gcd(3,5) +# where +--> #0 at line gcd.rb:18 +# step a +Step argument 'a' needs to be a number. +# set forcestep on +force-stepping is on. +# step- ; step- +gcd.rb:6 +if a > b +# set forcestep off +force-stepping is off. +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6 + #1 at line gcd.rb:18 +# n 2 +gcd.rb:10 +return nil if a <= 0 +# step+ +gcd.rb:12 +if a == 1 or b-a == 0 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:12 + #1 at line gcd.rb:18 +# step 3 +gcd.rb:6 +if a > b +# step+ +gcd.rb:10 +return nil if a <= 0 +# where +--> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:10 + #1 Object.-(a#Fixnum, b#Fixnum) at line gcd.rb:15 + #2 at line gcd.rb:18 +# next+ +gcd.rb:12 +if a == 1 or b-a == 0 +# # finish +# quit diff --git a/test/data/test-init-cygwin.right b/test/data/test-init-cygwin.right new file mode 100644 index 0000000..8d683f3 --- /dev/null +++ b/test/data/test-init-cygwin.right @@ -0,0 +1,7 @@ +gcd-dbg.rb:18 +if a > b +(rdb:1) p Debugger::PROG_SCRIPT +"./gcd-dbg.rb" +(rdb:1) show args +Argument list to give program being debugged when it is started is "5". +(rdb:1) quit unconditionally diff --git a/test/data/test-init-osx.right b/test/data/test-init-osx.right new file mode 100644 index 0000000..a50319c --- /dev/null +++ b/test/data/test-init-osx.right @@ -0,0 +1,4 @@ +gcd-dbg.rb:18 +if a > b +"./gcd-dbg.rb" +Argument list to give program being debugged when it is started is "5". diff --git a/test/data/test-init.right b/test/data/test-init.right new file mode 100644 index 0000000..981c233 --- /dev/null +++ b/test/data/test-init.right @@ -0,0 +1,5 @@ +gcd-dbg.rb:18 +if a > b +(rdb:1) "./gcd-dbg.rb" +(rdb:1) Argument list to give program being debugged when it is started is "5". +(rdb:1) \ No newline at end of file diff --git a/test/data/trace.right b/test/data/trace.right new file mode 100644 index 0000000..ada9008 --- /dev/null +++ b/test/data/trace.right @@ -0,0 +1,23 @@ +Tracing(1):gcd.rb:4 def gcd(a, b) +Tracing(1):gcd.rb:18 gcd(3,5) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:15 return gcd(b-a, a) +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:6 if a > b +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:10 return nil if a <= 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:12 if a == 1 or b-a == 0 +Tracing(1):gcd.rb:13 return a diff --git a/test/dollar-0.rb b/test/dollar-0.rb new file mode 100755 index 0000000..9955e43 --- /dev/null +++ b/test/dollar-0.rb @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby +# A test to see that rdebug set's $0 properly. +puts $0 +puts __FILE__ + diff --git a/test/gcd-dbg-nox.rb b/test/gcd-dbg-nox.rb new file mode 100644 index 0000000..5b84c6e --- /dev/null +++ b/test/gcd-dbg-nox.rb @@ -0,0 +1,31 @@ +# This program is *NOT* supposed to be executable, but called +# via ruby (in order to test that restart provides a funky $:). +# This program is used to test that 'restart' works when we didn't call +# the debugger initially. + +TOP_SRC_DIR = File.join(File.expand_path(File.dirname(__FILE__), '..')) unless + defined?(TOP_SRC_DIR) + +$:.unshift File.join(TOP_SRC_DIR, 'ext') +$:.unshift File.join(TOP_SRC_DIR, 'lib') +$:.unshift File.join(TOP_SRC_DIR, 'cli') +require 'ruby-debug' +Debugger.init + +# GCD. We assume positive numbers +def gcd(a, b) + # Make: a <= b + debugger + if a > b + a, b = [b, a] + end + + return nil if a <= 0 + + if a == 1 or b-a == 0 + return a + end + return gcd(b-a, a) +end + +gcd(3,5) diff --git a/test/gcd-dbg.rb b/test/gcd-dbg.rb new file mode 100755 index 0000000..717518b --- /dev/null +++ b/test/gcd-dbg.rb @@ -0,0 +1,30 @@ +#!/usr/bin/env ruby +# This program is used to test that 'restart' works when we didn't call +# the debugger initially. + +TOP_SRC_DIR = File.join(File.expand_path(File.dirname(__FILE__), "..")) unless + defined?(TOP_SRC_DIR) + +$:.unshift File.join(TOP_SRC_DIR, "ext") +$:.unshift File.join(TOP_SRC_DIR, "lib") +$:.unshift File.join(TOP_SRC_DIR, "cli") +require 'ruby-debug' +Debugger.start + +# GCD. We assume positive numbers +def gcd(a, b) + # Make: a <= b + debugger + if a > b + a, b = [b, a] + end + + return nil if a <= 0 + + if a == 1 or b-a == 0 + return a + end + return gcd(b-a, a) +end + +gcd(3,5) diff --git a/test/gcd.rb b/test/gcd.rb new file mode 100644 index 0000000..184b8df --- /dev/null +++ b/test/gcd.rb @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby + +# GCD. We assume positive numbers +def gcd(a, b) + # Make: a <= b + if a > b + a, b = [b, a] + end + + return nil if a <= 0 + + if a == 1 or b-a == 0 + return a + end + return gcd(b-a, a) +end + +gcd(3,5) diff --git a/test/helper.rb b/test/helper.rb new file mode 100644 index 0000000..a675869 --- /dev/null +++ b/test/helper.rb @@ -0,0 +1,143 @@ +# Some common routines used in testing. + +require 'fileutils' +require 'yaml' +# require 'diff/lcs' +# require 'diff/lcs/hunk' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +module TestHelper + + # FIXME: turn args into a hash. + def run_debugger(testname, args='', outfile=nil, filter=nil, old_code=false, + debug_pgm='tdebug.rb') + rightfile = File.join('data', "#{testname}.right") + + outfile = "#{testname}.out" unless outfile + + if File.exists?(outfile) + FileUtils.rm(outfile) + end + + ENV['RDEBUG'] = debug_pgm + + if old_code + cmd = "/bin/sh #{File.join('..', 'runner.sh')} #{args} >#{outfile}" + else + cmd = "#{"#{load_ruby} #{load_params} "}../rdbg.rb #{args} > #{outfile}" + end + puts "'#{cmd}'" if $DEBUG + output = `#{cmd}` + + got_lines = File.read(outfile).split(/\n/) + correct_lines = File.read(rightfile).split(/\n/) + filter.call(got_lines, correct_lines) if filter + if cheap_diff(got_lines, correct_lines) + FileUtils.rm(outfile) + return true + end + return false + end + + def cheap_diff(got_lines, correct_lines) + if $DEBUG + got_lines.each_with_index do |line, i| + printf "%3d %s\n", i+1, line + end + end + correct_lines.each_with_index do |line, i| + correct_lines[i].chomp! + if got_lines[i] != correct_lines[i] + puts "difference found at line #{i+1}" + puts "got : #{got_lines[i]}" + puts "need: #{correct_lines[i]}" + return false + end + end + if correct_lines.size != got_lines.size + puts("difference in number of lines: " + + "#{correct_lines.size} vs. #{got_lines.size}") + return false + end + return true + end + + # FIXME: using this causes the same test to get run several times + # and some tests fail probably because of a lack of environment isolation. + # Many tests follow a basic pattern: run the debugger with a given + # debugger script and compare output produced. The following creates + # this kind of test. + def add_test(base_name, src_dir, script_name=nil, cmd=nil, test_name=nil) + puts "+++ Adding #{base_name} ++++" if $DEBUG + test_name = base_name unless test_name + script_name = File.join('data', test_name + '.cmd') unless script_name + cmd = 'gcd.rb 3 5' unless cmd + eval <<-EOF + def test_#{test_name} + Dir.chdir(\"#{src_dir}\") do + assert_equal(true, + run_debugger(\"#{base_name}\", + \"--script #{script_name} -- #{cmd}\")) + end + end + EOF + end + module_function :add_test + + # Adapted from the Ruby Cookbook, Section 6.10: Comparing two files. + # def diff_as_string(rightfile, checkfile, format=:unified, context_lines=3) + # right_data = File.read(rightfile) + # check_data = File.read(checkfile) + # output = '' + # diffs = Diff::LCS.diff(right_data, check_data) + # return output if diffs.empty? + # oldhunk = hunk = nil + # file_length_difference = 0 + # diffs.each do |piece| + # begin + # hunk = Diff::LCS::Hunk.new(right_data, check_data, piece, + # context_lines, file_length_difference) + # next unless oldhunk + # + # # Hunks may overlap, which is why we need to be careful when our + # # diff includes lines of context. Otherwise, we might print + # # redundant lines. + # if (context_lines > 0) and hunk.overlaps?(oldhunk) + # hunk.unshift(oldhunk) + # else + # output << oldhunk.diff(format) + # end + # ensure + # oldhunk = hunk + # output << '\n' + # end + # end + + # # Handle the last remaining hunk + # output << oldhunk.diff(format) << '\n' + # end + + # Loads key from the _config_._yaml_ file. + def config_load(key, may_be_nil=false, default_value='') + conf = File.join('config.private.yaml') # try private first + conf = File.join('config.yaml') unless File.exists?(conf) + value = YAML.load_file(conf)[key] + assert_not_nil(value, "#{key} is set in config.yaml") unless may_be_nil + value || default_value + end + module_function :config_load + + def load_ruby + config_load('ruby', true) + end + module_function :load_ruby + + def load_params + config_load('ruby_params', true) + end + module_function :load_params + +end + diff --git a/test/info-var-bug.rb b/test/info-var-bug.rb new file mode 100644 index 0000000..9250e6e --- /dev/null +++ b/test/info-var-bug.rb @@ -0,0 +1,47 @@ +class Lousy_inspect + attr_accessor :var + def inspect # An unhelpful inspect + throw "Foo" # Raises an exception + end + def initialize + @var = 'initialized' + end +end +class Lousy_inspect_and_to_s + attr_accessor :var + def inspect # An unhelpful inspect + throw "Foo" # Raises an exception + end + def to_s # An unhelpful to_s + throw "bar" # Raises an exception + end + def initialize + @var = 'initialized' # Something to inspect + end +end + +# Something that will be passed objects with +# bad inspect or to_s methods +class UnsuspectingClass + @@Const = 'A constant' + @@var = 'a class variable' + def initialize(a) + @a = a # "info locals" will try to use + # inspect or to_s here + @b = 5 + end +end +def test_Lousy_inspect + x = Lousy_inspect.new + return x +end +def test_lousy_inspect_and_to_s + x = Lousy_inspect_and_to_s.new + return x +end +x = test_Lousy_inspect +y = test_lousy_inspect_and_to_s +UnsuspectingClass.new(10) +UnsuspectingClass.new(x) +UnsuspectingClass.new(y) +y = 2 diff --git a/test/info-var-bug2.rb b/test/info-var-bug2.rb new file mode 100644 index 0000000..83d474e --- /dev/null +++ b/test/info-var-bug2.rb @@ -0,0 +1,2 @@ +s = '<%= PRODUCT[:name] %>' +y = 0 diff --git a/test/null.rb b/test/null.rb new file mode 100644 index 0000000..47f0a27 --- /dev/null +++ b/test/null.rb @@ -0,0 +1 @@ +# Nothing here. Move along. diff --git a/test/output.rb b/test/output.rb new file mode 100644 index 0000000..69fde1b --- /dev/null +++ b/test/output.rb @@ -0,0 +1,2 @@ +puts "one" +puts "two" diff --git a/test/pm-base.rb b/test/pm-base.rb new file mode 100755 index 0000000..8d29f2f --- /dev/null +++ b/test/pm-base.rb @@ -0,0 +1,22 @@ +#!/usr/bin/env ruby +# Test post-mortem handling using only ruby-debug-base. +src_dir = File.dirname(__FILE__) +%w(ext lib cli).each do |dir| + $:.unshift File.join(src_dir, '..', dir) +end +require 'ruby-debug-base' + +class CommandProcessor + def at_line(context, file, line) + puts 'file: %s, line: %s' % [ File.basename(file), line ] + exit! + end +end + +Debugger.start(:post_mortem => true) +Debugger.handler = CommandProcessor.new +def zero_div + 1/0 +end +zero_div + diff --git a/test/pm-bug.rb b/test/pm-bug.rb new file mode 100644 index 0000000..3ced249 --- /dev/null +++ b/test/pm-bug.rb @@ -0,0 +1,3 @@ +a = 1 +@x = 2 +raise diff --git a/test/pm.rb b/test/pm.rb new file mode 100755 index 0000000..f8f0014 --- /dev/null +++ b/test/pm.rb @@ -0,0 +1,11 @@ +#!/ursr/bin/env ruby +# Test Debugger.catchpoint and post-mortem handling +def zero_div + x = 5 + 1/0 +end +x = 2 +zero_div +raise RuntimeError +x = 3 + diff --git a/test/raise.rb b/test/raise.rb new file mode 100755 index 0000000..c6f3b51 --- /dev/null +++ b/test/raise.rb @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby + +raise "abc" diff --git a/test/rdebug-save.1 b/test/rdebug-save.1 new file mode 100644 index 0000000..f759154 --- /dev/null +++ b/test/rdebug-save.1 @@ -0,0 +1,7 @@ +break gcd.rb:10 +break gcd.rb:12 if a > b +set autoeval on +set basename off +set debuggertesting off +set autolist off +set autoirb off diff --git a/test/runall b/test/runall new file mode 100755 index 0000000..634981b --- /dev/null +++ b/test/runall @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +#-*- Ruby -*- +debug_opt = '-d ' if $DEBUG or 'd' == ARGV[0] +for file in Dir.glob("test-*.rb") do + puts "=" * 50 + puts "== running #{file}..." + system("ruby #{file}"); +end +if ARGV[0] == "really" + system("(cd test && ruby #{debug_opt}runall)") + system("(cd examples && ruby #{debug_opt}runall)") +end diff --git a/test/tdebug.rb b/test/tdebug.rb new file mode 100755 index 0000000..ae13f3e --- /dev/null +++ b/test/tdebug.rb @@ -0,0 +1,252 @@ +#!/usr/bin/env ruby +# -*- Ruby -*- +# This is a hacked down copy of rdebug which can be used for testing +# FIXME: use the real rdebug script - DRY. + +require 'stringio' +require 'rubygems' +require 'optparse' +require "ostruct" + +TOP_SRC_DIR = File.join(File.dirname(__FILE__), "..") unless + defined?(TOP_SRC_DIR) + +$:.unshift File.join(TOP_SRC_DIR, "ext") +$:.unshift File.join(TOP_SRC_DIR, "lib") +$:.unshift File.join(TOP_SRC_DIR, "cli") + +def debug_program(options) + # Make sure Ruby script syntax checks okay. + # Otherwise we get a load message that looks like rdebug has + # a problem. + output = `ruby -c "#{Debugger::PROG_SCRIPT}" 2>&1` + if $?.exitstatus != 0 and RUBY_PLATFORM !~ /mswin/ + puts output + exit $?.exitstatus + end + print "\032\032starting\n" if Debugger.annotate and Debugger.annotate > 2 + unless options.no_rewrite_program + # Set $0 so things like __FILE == $0 work. + # A more reliable way to do this is to put $0 = __FILE__ *after* + # loading the script to be debugged. For this, adding a debug hook + # for the first time and then switching to the debug hook that's + # normally used would be helpful. Doing this would also help other + # first-time initializations such as reloading debugger state + # after a restart. + + # However This is just a little more than I want to take on right + # now, so I think I'll stick with the slightly hacky approach. + $RDEBUG_0 = $0 + + # cygwin does some sort of funky truncation on $0 ./abcdef => ./ab + # probably something to do with 3-letter extension truncation. + # The hacky workaround is to do slice assignment. Ugh. + d0 = if '.' == File.dirname(Debugger::PROG_SCRIPT) and + Debugger::PROG_SCRIPT[0..0] != '.' + File.join('.', Debugger::PROG_SCRIPT) + else + Debugger::PROG_SCRIPT + end + if $0.frozen? + $0 = d0 + else + $0[0..-1] = d0 + end + end + + # Record where we are we can know if the call stack has been + # truncated or not. + Debugger.start_sentinal=caller(0)[1] + + bt = Debugger.debug_load(Debugger::PROG_SCRIPT, !options.nostop, false) + if bt + if options.post_mortem + Debugger.handle_post_mortem(bt) + else + print bt.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n" + print "Uncaught exception: #{bt}\n" + end + end +end + +options = OpenStruct.new( + 'annotate' => false, + 'emacs' => false, + 'frame_bind' => false, + 'no-quit' => false, + 'no-stop' => false, + 'nx' => false, + 'post_mortem' => false, + 'script' => nil, + 'tracing' => false, + 'verbose_long'=> false, + 'wait' => false +) + +require "ruby-debug" + +program = File.basename($0) +opts = OptionParser.new do |opts| + opts.banner = < -- +EOB + opts.separator "" + opts.separator "Options:" + opts.on("-A", "--annotate LEVEL", Integer, "Set annotation level") do + |Debugger.annotate| + end + opts.on("-d", "--debug", "Set $DEBUG=true") {$DEBUG = true} + opts.on("--emacs-basic", "Activates basic Emacs mode") do + ENV['EMACS'] = '1' + options.emacs = true + end + opts.on("--keep-frame-binding", "Keep frame bindings") do + options.frame_bind = true + end + opts.on("-m", "--post-mortem", "Activate post-mortem mode") do + options.post_mortem = true + end + opts.on("--no-control", "Do not automatically start control thread") do + options.control = false + end + opts.on("--no-quit", "Do not quit when script finishes") do + options.noquit = true + end + opts.on("--no-stop", "Do not stop when script is loaded") do + options.nostop = true + end + opts.on("-nx", "Not run debugger initialization files (e.g. .rdebugrc") do + options.nx = true + end + opts.on("-I", "--include PATH", String, "Add PATH to $LOAD_PATH") do |path| + $LOAD_PATH.unshift(path) + end + opts.on("-r", "--require SCRIPT", String, + "Require the library, before executing your script") do |name| + if name == 'debug' + puts "ruby-debug is not compatible with Ruby's 'debug' library. This option is ignored." + else + require name + end + end + opts.on("--script FILE", String, "Name of the script file to run") do |options.script| + unless File.exists?(options.script) + puts "Script file '#{options.script}' is not found" + exit + end + end + opts.on("-x", "--trace", "Turn on line tracing") {options.tracing = true} + ENV['EMACS'] = nil unless options.emacs + opts.separator "" + opts.separator "Common options:" + opts.on_tail("--help", "Show this message") do + puts opts + exit + end + opts.on_tail("--version", + "Print the version") do + puts "ruby-debug #{Debugger::VERSION}" + exit + end + opts.on("--verbose", "Turn on verbose mode") do + $VERBOSE = true + options.verbose_long = true + end + opts.on_tail("-v", + "Print version number, then turn on verbose mode") do + puts "ruby-debug #{Debugger::VERSION}" + $VERBOSE = true + end +end + +begin + if not defined? Debugger::ARGV + Debugger::ARGV = ARGV.clone + end + rdebug_path = File.expand_path($0) + if RUBY_PLATFORM =~ /mswin/ + rdebug_path += '.cmd' unless rdebug_path =~ /\.cmd$/i + end + Debugger::RDEBUG_SCRIPT = rdebug_path + Debugger::RDEBUG_FILE = __FILE__ + Debugger::INITIAL_DIR = Dir.pwd + opts.parse! ARGV +rescue StandardError => e + puts opts + puts + puts e.message + exit(-1) +end + +if ARGV.empty? + exit if $VERBOSE and not options.verbose_long + puts opts + puts + puts 'Must specify a script to run' + exit(-1) +end + +# save script name +Debugger::PROG_SCRIPT = ARGV.shift + +# install interruption handler +trap('INT') { Debugger.interrupt_last } + +# set options +Debugger.wait_connection = false +Debugger.keep_frame_binding = options.frame_bind + +# Add Debugger trace hook. +Debugger.start + +# start control thread +Debugger.start_control(options.host, options.cport) if options.control + +# activate post-mortem +Debugger.post_mortem if options.post_mortem + +# Set up an interface to read commands from a debugger script file. +if options.script + Debugger.interface = Debugger::ScriptInterface.new(options.script, + STDOUT, true) +end +options.nostop = true if options.tracing +Debugger.tracing = options.tracing + +# Make sure Ruby script syntax checks okay. +# Otherwise we get a load message that looks like rdebug has +# a problem. +output = `ruby -c #{Debugger::PROG_SCRIPT} 2>&1` +if $?.exitstatus != 0 and RUBY_PLATFORM !~ /mswin/ + puts output + exit $?.exitstatus +end + +# load initrc script (e.g. .rdebugrc) +Debugger.run_init_script(StringIO.new) unless options.nx + +# run startup script if specified +if options.script + Debugger.run_script(options.script) +end +# activate post-mortem +Debugger.post_mortem if options.post_mortem +options.stop = false if options.tracing +Debugger.tracing = options.tracing + +if options.noquit + if Debugger.started? + until Debugger.stop do end + end + debug_program(options) + print "The program finished.\n" unless + Debugger.annotate.to_i > 1 # annotate has its own way + interface = Debugger::LocalInterface.new + # Not sure if ControlCommandProcessor is really the right + # thing to use. CommandProcessor requires a state. + processor = Debugger::ControlCommandProcessor.new(interface) + processor.process_commands +else + debug_program(options) +end diff --git a/test/test-annotate.rb b/test/test-annotate.rb new file mode 100755 index 0000000..27adff1 --- /dev/null +++ b/test/test-annotate.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' +require 'fileutils' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test annotate handling. +class TestAnnotate < Test::Unit::TestCase + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='annotate' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-break-bad.rb b/test/test-break-bad.rb new file mode 100755 index 0000000..f667ff7 --- /dev/null +++ b/test/test-break-bad.rb @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test (mostly) invalid breakpoint commands +class TestBadBreak < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='break_bad' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end + + def test_break_loop + testname='break_loop_bug' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- bp_loop_issue.rb")) + end + end + +end diff --git a/test/test-breakpoints.rb b/test/test-breakpoints.rb new file mode 100755 index 0000000..aa7617e --- /dev/null +++ b/test/test-breakpoints.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test breakpoint commands +class TestBreakpoints < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='breakpoints' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-catch.rb b/test/test-catch.rb new file mode 100755 index 0000000..fc7ef91 --- /dev/null +++ b/test/test-catch.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test condition command +class TestBreakpoints < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='catch' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- pm.rb")) + end + end +end diff --git a/test/test-condition.rb b/test/test-condition.rb new file mode 100755 index 0000000..9fea498 --- /dev/null +++ b/test/test-condition.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test condition command +class TestBreakpoints < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='condition' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-ctrl.rb b/test/test-ctrl.rb new file mode 100755 index 0000000..213b592 --- /dev/null +++ b/test/test-ctrl.rb @@ -0,0 +1,55 @@ +#!/usr/bin/env ruby + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug' ; Debugger.start + +require 'test/unit' +SRC_DIR = File.dirname(__FILE__) unless + defined?(SRC_DIR) +%w(ext lib cli).each do |dir| + $: << File.join(SRC_DIR, '..', dir) +end +require 'ruby_debug' +require File.join(SRC_DIR, '..', 'cli', 'ruby-debug') + +# Test Local Control Interface +class TestCtrl < Test::Unit::TestCase + + def cheap_diff(got_lines, correct_lines, outfile) + if correct_lines.size != got_lines.size + puts "Size difference #{correct_lines.size} vs. #{got_lines.size}" + File.open(outfile, 'w') {|f| f.puts got_lines} + return false + end + correct_lines.each_with_index do |line, i| + correct_lines[i].chomp! + if got_lines[i] != correct_lines[i] + puts "difference found at line #{i+1}" + puts "got : #{got_lines[i]}" + puts "need: #{correct_lines[i]}" + File.open(outfile, 'w') {|f| f.puts got_lines} + return false + end + end + end + + require 'stringio' + + # Test initial variables and setting/getting state. + def test_ctrl + ENV['COLUMNS'] = '80' + ENV['EMACS'] = nil + testbase = 'ctrl' + out = StringIO.new('', 'w') + Dir.chdir(SRC_DIR) do + script = File.join('data', "#{testbase}.cmd") + interface = Debugger::ScriptInterface.new(script, out) + processor = Debugger::ControlCommandProcessor.new(interface) + processor.process_commands + got_lines = out.string.split("\n") + right_file = File.join('data', "#{testbase}.right") + correct_lines = File.readlines(right_file) + assert cheap_diff(got_lines, correct_lines, "#{testbase}.out") + end + end +end diff --git a/test/test-display.rb b/test/test-display.rb new file mode 100755 index 0000000..4810a44 --- /dev/null +++ b/test/test-display.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Display commands +class TestDisplay < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test commands in display.rb + def test_basic + testname='display' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-dollar-0.rb b/test/test-dollar-0.rb new file mode 100755 index 0000000..8aa1346 --- /dev/null +++ b/test/test-dollar-0.rb @@ -0,0 +1,45 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test --no-stop and $0 setting. +class TestDollar0 < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='breakpoints' + Dir.chdir(@@SRC_DIR) do + home_save = ENV['HOME'] + ENV['HOME'] = '.' + filter = Proc.new{|got_lines, correct_lines| + [got_lines, correct_lines].flatten.each do |s| + s.gsub!(/.*dollar-0.rb$/, 'dollar-0.rb') + end + } + + assert_equal(true, + run_debugger('dollar-0', + '-nx --no-stop ./dollar-0.rb', + nil, filter, false, '../bin/rdebug')) + # Ruby's __FILE__ seems to prepend ./ when no directory was added. + assert_equal(true, + run_debugger('dollar-0a', + '-nx --no-stop dollar-0.rb', + nil, filter, false, '../bin/rdebug')) + # Ruby's __FILE__ seems to prepend ./ when no directory was added. + assert_equal(true, + run_debugger('dollar-0b', + '-nx --no-stop ' + + File.join('..', 'test', 'dollar-0.rb'), + nil, filter, false, '../bin/rdebug')) + ENV['HOME'] = home_save + end + end +end diff --git a/test/test-edit.rb b/test/test-edit.rb new file mode 100755 index 0000000..27ef6c1 --- /dev/null +++ b/test/test-edit.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test 'edit' command handling. +class TestEdit < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='edit' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + ENV['EDITOR']='echo FAKE-EDITOR ' + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-emacs-basic.rb b/test/test-emacs-basic.rb new file mode 100755 index 0000000..c4c5518 --- /dev/null +++ b/test/test-emacs-basic.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start(:post_mortem => true) + +# Test the --emacs-basic option. +class TestEmacsBasic < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper.rb') + + include TestHelper + + def test_basic + testname='emacs_basic' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--emacs-basic --script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-enable.rb b/test/test-enable.rb new file mode 100755 index 0000000..db73ffe --- /dev/null +++ b/test/test-enable.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test enable and disable commands +class TestEnable < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='enable' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-finish.rb b/test/test-finish.rb new file mode 100755 index 0000000..4f452cf --- /dev/null +++ b/test/test-finish.rb @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start + +# Test finish command +class TestFinish < Test::Unit::TestCase + + @@src_dir = File.dirname(__FILE__) unless + defined?(@@src_dir) + + require File.join(@@src_dir, 'helper') + include TestHelper + + def test_basic + testname='finish' + # Ruby 1.8.6 and earlier have a trace-line number bug for return + # statements. +# filter = Proc.new{|got_lines, correct_lines| +# [got_lines[31], got_lines[34]].flatten.each do |s| +# s.sub!(/gcd.rb:\d+/, 'gcd.rb:13') +# end +# got_lines[32] = 'return a' +# } + Dir.chdir(@@src_dir) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", + nil, nil)) + end + end +end diff --git a/test/test-frame.rb b/test/test-frame.rb new file mode 100755 index 0000000..c5f059f --- /dev/null +++ b/test/test-frame.rb @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start(:post_mortem => true) + +# Test frame commands +class TestFrame < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test commands in frame.rb + def test_basic + testname='frame' + # Ruby 1.8.6 and earlier have a trace-line number bug for return + # statements. + filter = Proc.new{|got_lines, correct_lines| + [got_lines[11], correct_lines[11]].flatten.each do |s| + s.sub!(/in file ".*gcd.rb/, 'in file "gcd.rb') + end + } + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", + nil, filter)) + end + end +end diff --git a/test/test-help.rb b/test/test-help.rb new file mode 100755 index 0000000..460dd6c --- /dev/null +++ b/test/test-help.rb @@ -0,0 +1,60 @@ +#!/usr/bin/env ruby + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug' ; Debugger.start + +require 'test/unit' +SRC_DIR = File.dirname(__FILE__) unless + defined?(SRC_DIR) +%w(ext lib cli).each do |dir| + $:.unshift File.join(SRC_DIR, '..', dir) +end +require 'ruby_debug' + +require File.join(SRC_DIR, '..', 'cli', 'ruby-debug') +$:.shift; $:.shift; $:.shift + +def cheap_diff(got_lines, correct_lines) + puts got_lines if $DEBUG + correct_lines.each_with_index do |line, i| + correct_lines[i].chomp! + if got_lines[i] != correct_lines[i] + puts "difference found at line #{i+1}" + puts "got : #{got_lines[i]}" + puts "need: #{correct_lines[i]}" + return false + end + if correct_lines.size != got_lines.size + puts("difference in number of lines: " + + "#{correct_lines.size} vs. #{got_lines.size}") + return false + end + return true + end +end + +# Test Help commands +class TestHelp < Test::Unit::TestCase + require 'stringio' + + # Test initial variables and setting/getting state. + def test_basic + testbase = 'help' + op = StringIO.new('', 'w') + Dir.chdir(SRC_DIR) do + script = File.join('data', "#{testbase}.cmd") + Debugger.const_set('Version', 'unit testing') + Debugger.run_script(script, op) + got_lines = op.string.split("\n") + right_file = File.join('data', "#{testbase}.right") + correct_lines = File.readlines(right_file) + result = cheap_diff(got_lines, correct_lines) + unless result + puts '-' * 80 + puts got_lines + puts '-' * 80 + end + assert result + end + end +end diff --git a/test/test-hist.rb b/test/test-hist.rb new file mode 100755 index 0000000..484394c --- /dev/null +++ b/test/test-hist.rb @@ -0,0 +1,68 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test history commands + +class TestHistory < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + unless defined?(@@FILE_HISTORY) + @@FILE_HISTORY = '.rdebug_hist' + end + + def test_basic + + # Set up history file to read from. + ENV['HOME']=@@SRC_DIR + ENV['RDEBUG'] = nil + + debugger_commands = ['show commands', + 'set history save on', + 'show history', + 'quit unconditionally'] + debugger_output = 'test-history.out' + + Dir.chdir(@@SRC_DIR) do + correct_lines = File.read(File.join('data', 'history.right')).split(/\n/) + f = File.open(@@FILE_HISTORY, 'w') + correct_lines[0.. -(debugger_commands.length+1)].each do |line| + f.puts line + end + f.close + + # Now that we've set up a history file, run the debugger + # and check that it's reading that correctly. + debug_pgm=File.join('..', 'rdbg.rb') + debugged=File.join('gcd.rb') + IO.popen("#{debug_pgm} #{debugged} 3 5 >#{debugger_output}", 'w') do + |pipe| + debugger_commands.each do |cmd| + pipe.puts cmd + end + end + + # Compare output + got_lines = File.read(@@FILE_HISTORY).split(/\n/) + # FIXME: Disable for now. + assert true, 'FIXME' + return + if cheap_diff(got_lines, correct_lines) + assert true + FileUtils.rm(debugger_output) + FileUtils.rm(@@FILE_HISTORY) + else + assert nil, 'Output differs' + end + end + end +end + + diff --git a/test/test-info-thread.rb b/test/test-info-thread.rb new file mode 100755 index 0000000..d90cc8a --- /dev/null +++ b/test/test-info-thread.rb @@ -0,0 +1,32 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test simple thread commands +class TestInfoThread < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='info-thread' + Dir.chdir(@@SRC_DIR) do + filter = Proc.new{|got_lines, correct_lines| + [got_lines, correct_lines].each do |a| + a.each do |s| + s.sub!(/Thread:0x[0-9a-f]+/, 'Thread:0x12345678') + end + end + } + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", nil, filter)) + end + end +end diff --git a/test/test-info-var.rb b/test/test-info-var.rb new file mode 100755 index 0000000..af06c78 --- /dev/null +++ b/test/test-info-var.rb @@ -0,0 +1,47 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test info variables command +class TestInfoVar < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_info_variables + + Dir.chdir(@@SRC_DIR) do + + filter = Proc.new{|got_lines, correct_lines| + [got_lines[13-1], correct_lines[13-1]].each do |s| + s.sub!(/Mine:0x[0-9,a-f]+/, 'Mine:') + end + [got_lines, correct_lines].each do |a| + a.each do |s| + s.sub!(/Lousy_inspect:0x[0-9,a-f]+/, 'Lousy_inspect:') + s.sub!(/UnsuspectingClass:0x[0-9,a-f]+/, 'UnsuspectingClass:') + end + end + } + + testname='info-var' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- info-var-bug.rb", + nil, filter)) + testname='info-var-bug2' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- info-var-bug2.rb", + nil)) + + end + end +end diff --git a/test/test-info.rb b/test/test-info.rb new file mode 100755 index 0000000..dade3c8 --- /dev/null +++ b/test/test-info.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test info commands +class TestInfo < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test commands in info.rb + def test_basic + testname='info' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-init.rb b/test/test-init.rb new file mode 100755 index 0000000..bbc2394 --- /dev/null +++ b/test/test-init.rb @@ -0,0 +1,43 @@ +#!/usr/bin/env ruby +require 'test/unit' +require 'rbconfig' +require File.join(File.dirname(__FILE__), 'helper.rb') + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Debugger.init and setting up ruby-debug variables +class TestDebuggerInit < Test::Unit::TestCase + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + def test_basic + debugger_output = 'test-init.out' + Dir.chdir(@@SRC_DIR) do + old_emacs = ENV['EMACS'] + old_columns = ENV['COLUMNS'] + ENV['EMACS'] = nil + ENV['COLUMNS'] = '120' + ruby = "#{TestHelper.load_ruby} #{TestHelper.load_params}" + IO.popen("#{ruby} ./gcd-dbg.rb 5 >#{debugger_output}", 'w') do |pipe| + pipe.puts 'p Debugger::PROG_SCRIPT' + pipe.puts 'show args' + pipe.puts 'quit unconditionally' + end + lines = File.open(debugger_output).readlines + ENV['EMACS'] = old_emacs + ENV['COLUMNS'] = old_columns + + right_file = case Config::CONFIG['host_os'] + when /^darwin/ + 'test-init-osx.right' + when /^cygwin/ + 'test-init-cygwin.right' + else + 'test-init.right' + end + expected = File.open(File.join('data', right_file)).readlines + assert_equal(expected, lines) + File.delete(debugger_output) if expected == lines + end + end +end diff --git a/test/test-list.rb b/test/test-list.rb new file mode 100755 index 0000000..12c2680 --- /dev/null +++ b/test/test-list.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test List commands +class TestList < Test::Unit::TestCase + + @@src_dir = File.dirname(__FILE__) + + require File.join(@@src_dir, 'helper') + include TestHelper + + # Test commands in list.rb + def test_basic + testname='list' + Dir.chdir(@@src_dir) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-method.rb b/test/test-method.rb new file mode 100755 index 0000000..a8da23b --- /dev/null +++ b/test/test-method.rb @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start(:post_mortem => true) + +class TestMethod < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='method' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- classes.rb")) + begin + require 'methodsig' + testname='methodsig' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- classes.rb")) + rescue LoadError + puts "Skipping method sig test" + end + end + end +end diff --git a/test/test-output.rb b/test/test-output.rb new file mode 100755 index 0000000..9435113 --- /dev/null +++ b/test/test-output.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test 'starting' annotation. +class TestStartingAnnotate < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='output' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "-A 3 --script #{script} -- output.rb", + nil, nil, true)) + end + end +end diff --git a/test/test-pm.rb b/test/test-pm.rb new file mode 100755 index 0000000..cc646cc --- /dev/null +++ b/test/test-pm.rb @@ -0,0 +1,59 @@ +#!/usr/bin/env ruby +require 'test/unit' +require 'rbconfig' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Post-mortem command +class TestPM < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test post-mortem handling + def test_basic + Dir.chdir(@@SRC_DIR) do +# filter = Proc.new{|got_lines, correct_lines| +# [got_lines[0], correct_lines[0]].each do |s| +# s.sub!(/tdebug.rb:\d+/, 'rdebug:999') +# end +# } + ENV['COLUMNS'] = '80' + testname='post-mortem' + script = File.join('data', testname + '.cmd') + testname += '-osx' if Config::CONFIG['host_os'] =~ /^darwin/ + assert_equal(true, + run_debugger(testname, + "--script #{script} --post-mortem pm.rb")) + end + end + + # Test post-mortem handling + def test_pm_next + Dir.chdir(@@SRC_DIR) do + ENV['COLUMNS'] = '80' + testname='post-mortem-next' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} --post-mortem pm.rb")) + end + end + + # Test Tracker #22118 post-mortem giving an error in show internal variables + def test_pm_iv_bug + Dir.chdir(@@SRC_DIR) do + ENV['COLUMNS'] = '80' + testname='pm-bug' + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} --post-mortem pm-bug.rb")) + end + end + +end diff --git a/test/test-quit.rb b/test/test-quit.rb new file mode 100755 index 0000000..2a313b8 --- /dev/null +++ b/test/test-quit.rb @@ -0,0 +1,30 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Quit command +class TestQuit < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='quit' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') +# filter = Proc.new{|got_lines, correct_lines| +# [got_lines[0], correct_lines[0]].each do |s| +# s.sub!(/tdebug.rb:\d+/, 'rdebug:999') +# end +# } + assert_equal(true, + run_debugger(testname, + "--script #{script} -- null.rb")) + end + end +end diff --git a/test/test-raise.rb b/test/test-raise.rb new file mode 100755 index 0000000..c111b9e --- /dev/null +++ b/test/test-raise.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test Debugger.load handles uncaught exceptions in the debugged program. +class TestBreakpoints < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='raise' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- raise.rb")) + end + end +end diff --git a/test/test-save.rb b/test/test-save.rb new file mode 100755 index 0000000..6d8c6b0 --- /dev/null +++ b/test/test-save.rb @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# require 'rubygems' +# require 'ruby-debug'; Debugger.start(:post_mortem =>true) + +class TestSave < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test initial variables and setting/getting state. + def test_basic + testname='save' + filter = Proc.new{|got_lines, correct_lines| + got_lines.each do |s| + s.sub!(/2 file .*gcd.rb/, '2 file gcd.rb') + end + } + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", + nil, filter)) + end + end +end diff --git a/test/test-setshow.rb b/test/test-setshow.rb new file mode 100755 index 0000000..1710965 --- /dev/null +++ b/test/test-setshow.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +class TestSetShow < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test initial variables and setting/getting state. + def test_basic + testname='setshow' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-source.rb b/test/test-source.rb new file mode 100755 index 0000000..b6c1629 --- /dev/null +++ b/test/test-source.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test 'source' command handling. +class TestSource < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_basic + testname='source' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-stepping.rb b/test/test-stepping.rb new file mode 100755 index 0000000..8c4f404 --- /dev/null +++ b/test/test-stepping.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test that linetracing does something. +class TestStepping < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + # Test commands in stepping.rb + def test_basic + testname='stepping' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5")) + end + end +end diff --git a/test/test-trace.rb b/test/test-trace.rb new file mode 100755 index 0000000..7e64ed0 --- /dev/null +++ b/test/test-trace.rb @@ -0,0 +1,63 @@ +#!/usr/bin/env ruby +require 'test/unit' + +# begin require 'rubygems' rescue LoadError end +# require 'ruby-debug'; Debugger.start + +# Test 'edit' command handling. +class TestEdit < Test::Unit::TestCase + + @@SRC_DIR = File.dirname(__FILE__) unless + defined?(@@SRC_DIR) + + require File.join(@@SRC_DIR, 'helper') + include TestHelper + + def test_trace_option + + filter = Proc.new{|got_lines, correct_lines| + got_lines.collect!{|l| l =~ /:gcd\.rb:/? l : nil}.compact! + } + + testname='trace' + Dir.chdir(@@SRC_DIR) do + assert_equal(true, + run_debugger(testname, + "-nx --trace gcd.rb 3 5", nil, filter)) + end + end + + def test_linetrace_command + + filter = Proc.new{|got_lines, correct_lines| + got_lines.collect!{|l| l !~ /:rdbg\.rb:/? l : nil}.compact! + } + + testname='linetrace' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", nil, + filter)) + + end + end + + def test_linetrace_plus_command + + filter = Proc.new{|got_lines, correct_lines| + got_lines.collect!{|l| l !~ /:rdbg\.rb:/? l : nil}.compact! + } + + testname='linetracep' + Dir.chdir(@@SRC_DIR) do + script = File.join('data', testname + '.cmd') + assert_equal(true, + run_debugger(testname, + "--script #{script} -- gcd.rb 3 5", nil, + filter)) + + end + end +end diff --git a/test/thread1.rb b/test/thread1.rb new file mode 100644 index 0000000..26bdf3b --- /dev/null +++ b/test/thread1.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +# Adapted from Programming Ruby 2nd Ed. p. 138 +require 'rubygems' + +unless defined?(Debugger) + puts "This program has to be called from the debugger" + exit 1 +end + +def fn(count, i) + sleep(rand(0.1)) + if 4 == i + debugger + end + Thread.current['mycount'] = count +end + +count = 0 +threads = [] +5.times do |i| + threads[i] = Thread.new do + fn(count, i) + count += 1 + end + end +threads.each {|t| t.join } diff --git a/test/trunc-call.rb b/test/trunc-call.rb new file mode 100644 index 0000000..d892d4f --- /dev/null +++ b/test/trunc-call.rb @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# This program is used to test that 'restart' works when we didn't call +# the debugger initially. + +TOP_SRC_DIR = File.join(File.expand_path(File.dirname(__FILE__), "..")) unless + defined?(TOP_SRC_DIR) + +$:.unshift File.join(TOP_SRC_DIR, "ext") +$:.unshift File.join(TOP_SRC_DIR, "lib") +$:.unshift File.join(TOP_SRC_DIR, "cli") +require 'ruby-debug' + +# GCD. We assume positive numbers +def gcd(a, b) + # Make: a <= b + if a > b + a, b = [b, a] + end + if a==3 + Debugger.debugger + end + + return nil if a <= 0 + + if a == 1 or b-a == 0 + return a + end + return gcd(b-a, a) +end + +gcd(13,8)