needy_debugger 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. data/.gitignore +14 -0
  2. data/.travis.yml +8 -0
  3. data/AUTHORS +10 -0
  4. data/CHANGELOG.md +68 -0
  5. data/CONTRIBUTING.md +1 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +23 -0
  8. data/OLDER_CHANGELOG +334 -0
  9. data/OLD_CHANGELOG +5655 -0
  10. data/OLD_README +122 -0
  11. data/README.md +141 -0
  12. data/Rakefile +78 -0
  13. data/bin/rdebug +397 -0
  14. data/doc/.cvsignore +42 -0
  15. data/doc/Makefile.am +63 -0
  16. data/doc/emacs-notes.txt +38 -0
  17. data/doc/hanoi.rb +35 -0
  18. data/doc/primes.rb +28 -0
  19. data/doc/rdebug-emacs.texi +1030 -0
  20. data/doc/ruby-debug.texi +3791 -0
  21. data/doc/test-tri2.rb +18 -0
  22. data/doc/tri3.rb +8 -0
  23. data/doc/triangle.rb +12 -0
  24. data/emacs/Makefile.am +130 -0
  25. data/emacs/rdebug-annotate.el +385 -0
  26. data/emacs/rdebug-breaks.el +407 -0
  27. data/emacs/rdebug-cmd.el +92 -0
  28. data/emacs/rdebug-core.el +502 -0
  29. data/emacs/rdebug-dbg.el +62 -0
  30. data/emacs/rdebug-error.el +79 -0
  31. data/emacs/rdebug-fns.el +111 -0
  32. data/emacs/rdebug-frames.el +230 -0
  33. data/emacs/rdebug-gud.el +242 -0
  34. data/emacs/rdebug-help.el +104 -0
  35. data/emacs/rdebug-info.el +83 -0
  36. data/emacs/rdebug-layouts.el +180 -0
  37. data/emacs/rdebug-locring.el +118 -0
  38. data/emacs/rdebug-output.el +106 -0
  39. data/emacs/rdebug-regexp.el +118 -0
  40. data/emacs/rdebug-secondary.el +260 -0
  41. data/emacs/rdebug-shortkey.el +175 -0
  42. data/emacs/rdebug-source.el +568 -0
  43. data/emacs/rdebug-track.el +392 -0
  44. data/emacs/rdebug-varbuf.el +150 -0
  45. data/emacs/rdebug-vars.el +125 -0
  46. data/emacs/rdebug-watch.el +132 -0
  47. data/emacs/rdebug.el +326 -0
  48. data/emacs/test/elk-test.el +242 -0
  49. data/emacs/test/test-annotate.el +103 -0
  50. data/emacs/test/test-cmd.el +116 -0
  51. data/emacs/test/test-core.el +104 -0
  52. data/emacs/test/test-fns.el +65 -0
  53. data/emacs/test/test-frames.el +62 -0
  54. data/emacs/test/test-gud.el +35 -0
  55. data/emacs/test/test-indent.el +58 -0
  56. data/emacs/test/test-regexp.el +144 -0
  57. data/emacs/test/test-shortkey.el +61 -0
  58. data/ext/ruby_debug/192/breakpoint.c +586 -0
  59. data/ext/ruby_debug/192/ruby_debug.c +2645 -0
  60. data/ext/ruby_debug/192/ruby_debug.h +148 -0
  61. data/ext/ruby_debug/193/breakpoint.c +586 -0
  62. data/ext/ruby_debug/193/ruby_debug.c +2626 -0
  63. data/ext/ruby_debug/193/ruby_debug.h +148 -0
  64. data/ext/ruby_debug/200/breakpoint.c +586 -0
  65. data/ext/ruby_debug/200/ruby_debug.c +2692 -0
  66. data/ext/ruby_debug/200/ruby_debug.h +148 -0
  67. data/ext/ruby_debug/extconf.rb +94 -0
  68. data/lib/debugger.rb +5 -0
  69. data/lib/debugger/version.rb +5 -0
  70. data/lib/ruby-debug-base.rb +305 -0
  71. data/lib/ruby-debug.rb +177 -0
  72. data/lib/ruby-debug/command.rb +227 -0
  73. data/lib/ruby-debug/commands/breakpoints.rb +153 -0
  74. data/lib/ruby-debug/commands/catchpoint.rb +55 -0
  75. data/lib/ruby-debug/commands/condition.rb +49 -0
  76. data/lib/ruby-debug/commands/continue.rb +38 -0
  77. data/lib/ruby-debug/commands/control.rb +107 -0
  78. data/lib/ruby-debug/commands/display.rb +120 -0
  79. data/lib/ruby-debug/commands/edit.rb +48 -0
  80. data/lib/ruby-debug/commands/enable.rb +202 -0
  81. data/lib/ruby-debug/commands/eval.rb +176 -0
  82. data/lib/ruby-debug/commands/finish.rb +42 -0
  83. data/lib/ruby-debug/commands/frame.rb +301 -0
  84. data/lib/ruby-debug/commands/help.rb +56 -0
  85. data/lib/ruby-debug/commands/info.rb +467 -0
  86. data/lib/ruby-debug/commands/irb.rb +123 -0
  87. data/lib/ruby-debug/commands/jump.rb +66 -0
  88. data/lib/ruby-debug/commands/kill.rb +51 -0
  89. data/lib/ruby-debug/commands/list.rb +94 -0
  90. data/lib/ruby-debug/commands/method.rb +84 -0
  91. data/lib/ruby-debug/commands/quit.rb +50 -0
  92. data/lib/ruby-debug/commands/reload.rb +40 -0
  93. data/lib/ruby-debug/commands/save.rb +90 -0
  94. data/lib/ruby-debug/commands/set.rb +223 -0
  95. data/lib/ruby-debug/commands/show.rb +247 -0
  96. data/lib/ruby-debug/commands/skip.rb +35 -0
  97. data/lib/ruby-debug/commands/source.rb +36 -0
  98. data/lib/ruby-debug/commands/stepping.rb +81 -0
  99. data/lib/ruby-debug/commands/threads.rb +189 -0
  100. data/lib/ruby-debug/commands/tmate.rb +36 -0
  101. data/lib/ruby-debug/commands/trace.rb +57 -0
  102. data/lib/ruby-debug/commands/variables.rb +199 -0
  103. data/lib/ruby-debug/debugger.rb +5 -0
  104. data/lib/ruby-debug/helper.rb +69 -0
  105. data/lib/ruby-debug/interface.rb +232 -0
  106. data/lib/ruby-debug/processor.rb +474 -0
  107. data/man/rdebug.1 +241 -0
  108. data/needy_debugger.gemspec +31 -0
  109. data/old_scripts/Makefile.am +14 -0
  110. data/old_scripts/README.md +2 -0
  111. data/old_scripts/autogen.sh +4 -0
  112. data/old_scripts/configure.ac +12 -0
  113. data/old_scripts/rdbg.rb +33 -0
  114. data/old_scripts/runner.sh +7 -0
  115. data/old_scripts/svn2cl_usermap +3 -0
  116. data/test/.cvsignore +1 -0
  117. data/test/breakpoints_test.rb +365 -0
  118. data/test/conditions_test.rb +76 -0
  119. data/test/continue_test.rb +28 -0
  120. data/test/display_test.rb +141 -0
  121. data/test/edit_test.rb +55 -0
  122. data/test/eval_test.rb +92 -0
  123. data/test/examples/breakpoint1.rb +15 -0
  124. data/test/examples/breakpoint2.rb +7 -0
  125. data/test/examples/conditions.rb +4 -0
  126. data/test/examples/continue.rb +4 -0
  127. data/test/examples/display.rb +5 -0
  128. data/test/examples/edit.rb +3 -0
  129. data/test/examples/edit2.rb +3 -0
  130. data/test/examples/eval.rb +4 -0
  131. data/test/examples/finish.rb +20 -0
  132. data/test/examples/frame.rb +31 -0
  133. data/test/examples/help.rb +2 -0
  134. data/test/examples/info.rb +48 -0
  135. data/test/examples/info2.rb +3 -0
  136. data/test/examples/irb.rb +6 -0
  137. data/test/examples/jump.rb +14 -0
  138. data/test/examples/kill.rb +2 -0
  139. data/test/examples/list.rb +12 -0
  140. data/test/examples/method.rb +15 -0
  141. data/test/examples/post_mortem.rb +19 -0
  142. data/test/examples/quit.rb +2 -0
  143. data/test/examples/reload.rb +6 -0
  144. data/test/examples/restart.rb +6 -0
  145. data/test/examples/save.rb +3 -0
  146. data/test/examples/set.rb +3 -0
  147. data/test/examples/set_annotate.rb +12 -0
  148. data/test/examples/settings.rb +1 -0
  149. data/test/examples/show.rb +2 -0
  150. data/test/examples/source.rb +3 -0
  151. data/test/examples/stepping.rb +21 -0
  152. data/test/examples/thread.rb +32 -0
  153. data/test/examples/tmate.rb +10 -0
  154. data/test/examples/trace.rb +7 -0
  155. data/test/examples/trace_threads.rb +20 -0
  156. data/test/examples/variables.rb +26 -0
  157. data/test/finish_test.rb +48 -0
  158. data/test/frame_test.rb +140 -0
  159. data/test/help_test.rb +50 -0
  160. data/test/info_test.rb +325 -0
  161. data/test/irb_test.rb +81 -0
  162. data/test/jump_test.rb +70 -0
  163. data/test/kill_test.rb +47 -0
  164. data/test/list_test.rb +145 -0
  165. data/test/method_test.rb +70 -0
  166. data/test/post_mortem_test.rb +25 -0
  167. data/test/quit_test.rb +55 -0
  168. data/test/reload_test.rb +43 -0
  169. data/test/restart_test.rb +143 -0
  170. data/test/save_test.rb +92 -0
  171. data/test/set_test.rb +177 -0
  172. data/test/show_test.rb +292 -0
  173. data/test/source_test.rb +44 -0
  174. data/test/stepping_test.rb +118 -0
  175. data/test/support/breakpoint.rb +12 -0
  176. data/test/support/context.rb +14 -0
  177. data/test/support/matchers.rb +67 -0
  178. data/test/support/mocha_extensions.rb +71 -0
  179. data/test/support/processor.rb +7 -0
  180. data/test/support/test_dsl.rb +205 -0
  181. data/test/support/test_interface.rb +66 -0
  182. data/test/test_helper.rb +8 -0
  183. data/test/thread_test.rb +122 -0
  184. data/test/tmate_test.rb +43 -0
  185. data/test/trace_test.rb +154 -0
  186. data/test/variables_test.rb +114 -0
  187. metadata +352 -0
@@ -0,0 +1,148 @@
1
+ /* Context info */
2
+ enum ctx_stop_reason {CTX_STOP_NONE, CTX_STOP_STEP, CTX_STOP_BREAKPOINT,
3
+ CTX_STOP_CATCHPOINT};
4
+
5
+ /* Context flags */
6
+ #define CTX_FL_SUSPEND (1<<1)
7
+ #define CTX_FL_TRACING (1<<2)
8
+ #define CTX_FL_SKIPPED (1<<3)
9
+ #define CTX_FL_IGNORE (1<<4)
10
+ #define CTX_FL_DEAD (1<<5)
11
+ #define CTX_FL_WAS_RUNNING (1<<6)
12
+ #define CTX_FL_ENABLE_BKPT (1<<7)
13
+ #define CTX_FL_STEPPED (1<<8)
14
+ #define CTX_FL_FORCE_MOVE (1<<9)
15
+ #define CTX_FL_CATCHING (1<<10)
16
+
17
+ #define CTX_FL_TEST(c,f) ((c)->flags & (f))
18
+ #define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
19
+ #define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0)
20
+
21
+ typedef struct {
22
+ struct iseq_catch_table_entry tmp_catch_table;
23
+ struct iseq_catch_table_entry *old_catch_table;
24
+ int old_catch_table_size;
25
+ VALUE mod_name;
26
+ VALUE errinfo;
27
+ } debug_catch_t;
28
+
29
+ typedef struct {
30
+ struct rb_iseq_struct *iseq;
31
+ struct iseq_catch_table_entry *catch_table;
32
+ int catch_table_size;
33
+ } iseq_catch_t;
34
+
35
+ typedef struct {
36
+ int argc; /* Number of arguments a frame should have. */
37
+ VALUE binding;
38
+ ID id;
39
+ ID orig_id;
40
+ int line;
41
+ const char * file;
42
+ short dead;
43
+ VALUE self;
44
+ VALUE arg_ary;
45
+ union {
46
+ struct {
47
+ rb_control_frame_t *cfp;
48
+ VALUE *bp;
49
+ struct rb_iseq_struct *block_iseq;
50
+ VALUE *block_pc;
51
+ VALUE *last_pc;
52
+ } runtime;
53
+ struct {
54
+ VALUE args;
55
+ VALUE locals;
56
+ VALUE arg_ary;
57
+ } copy;
58
+ } info;
59
+ } debug_frame_t;
60
+
61
+ typedef struct {
62
+ VALUE thread_id;
63
+ int thnum;
64
+ int flags;
65
+ enum ctx_stop_reason stop_reason;
66
+ int stop_next;
67
+ int dest_frame;
68
+ int stop_line;
69
+ int stop_frame;
70
+ int stack_size;
71
+ int stack_len;
72
+ debug_frame_t *frames;
73
+ const char * last_file;
74
+ int last_line;
75
+ VALUE breakpoint;
76
+ debug_catch_t catch_table;
77
+ VALUE saved_jump_ins[2];
78
+ rb_control_frame_t *jump_cfp;
79
+ VALUE *jump_pc;
80
+ iseq_catch_t *old_iseq_catch;
81
+ volatile int thread_pause;
82
+ } debug_context_t;
83
+
84
+ /* variables in ruby_debug.c */
85
+ extern VALUE mDebugger;
86
+ extern VALUE rdebug_breakpoints;
87
+ extern VALUE rdebug_catchpoints;
88
+ extern VALUE rdebug_threads_tbl;
89
+
90
+ /* routines in ruby_debug.c */
91
+ extern int filename_cmp(VALUE source, char *file);
92
+
93
+ #define IS_STARTED (rdebug_threads_tbl != Qnil)
94
+ static inline void
95
+ debug_check_started()
96
+ {
97
+ if(!IS_STARTED)
98
+ {
99
+ rb_raise(rb_eRuntimeError, "Debugger.start is not called yet.");
100
+ }
101
+ }
102
+
103
+ static inline int
104
+ classname_cmp(VALUE name, VALUE klass)
105
+ {
106
+ VALUE mod_name;
107
+ VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name;
108
+ if (klass == Qnil) return(0);
109
+ mod_name = rb_mod_name(klass);
110
+ return (mod_name != Qnil
111
+ && rb_str_cmp(class_name, mod_name) == 0);
112
+ }
113
+
114
+ /* Breakpoint information */
115
+ enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
116
+ enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD};
117
+
118
+ typedef struct {
119
+ int id;
120
+ enum bp_type type;
121
+ VALUE source;
122
+ union
123
+ {
124
+ int line;
125
+ ID mid;
126
+ } pos;
127
+ VALUE expr;
128
+ VALUE enabled;
129
+ int hit_count;
130
+ int hit_value;
131
+ enum hit_condition hit_condition;
132
+ } debug_breakpoint_t;
133
+
134
+ /* routines in breakpoint.c */
135
+ extern int check_breakpoint_expression(VALUE breakpoint, VALUE binding);
136
+ extern int check_breakpoint_hit_condition(VALUE breakpoint);
137
+ extern VALUE check_breakpoints_by_method(debug_context_t *debug_context,
138
+ VALUE klass, ID mid, VALUE self);
139
+ extern VALUE check_breakpoints_by_pos(debug_context_t *debug_context,
140
+ char *file, int line);
141
+ extern VALUE create_breakpoint_from_args(int argc, VALUE *argv, int id);
142
+ extern VALUE context_breakpoint(VALUE self);
143
+ extern VALUE context_set_breakpoint(int argc, VALUE *argv, VALUE self);
144
+ extern VALUE rdebug_add_catchpoint(VALUE self, VALUE value);
145
+ extern VALUE debug_catchpoints(VALUE self);
146
+ extern VALUE rdebug_remove_breakpoint(VALUE self, VALUE id_value);
147
+
148
+ extern void Init_breakpoint();
@@ -0,0 +1,94 @@
1
+ # autodetect ruby headers
2
+ unless ARGV.any? {|arg| arg.include?('--with-ruby-include') }
3
+ require 'rbconfig'
4
+ bindir = RbConfig::CONFIG['bindir']
5
+ if bindir =~ %r{(^.*/\.rbenv/versions)/([^/]+)/bin$}
6
+ ruby_include = "#{$1}/#{$2}/include/ruby-#{RUBY_VERSION.start_with?("1.9") ? "1.9.1" : RUBY_VERSION}/ruby-#{$2}"
7
+ ARGV << "--with-ruby-include=#{ruby_include}"
8
+ elsif bindir =~ %r{(^.*/\.rvm/rubies)/([^/]+)/bin$}
9
+ ruby_include = "#{$1}/#{$2}/include/ruby-#{RUBY_VERSION.start_with?("1.9") ? "1.9.1" : RUBY_VERSION}/#{$2}"
10
+ ruby_include = "#{ENV['rvm_path']}/src/#{$2}" unless File.exist?(ruby_include)
11
+ ARGV << "--with-ruby-include=#{ruby_include}"
12
+ end
13
+ end
14
+
15
+ require "mkmf"
16
+ require "debugger/ruby_core_source"
17
+ require 'fileutils'
18
+
19
+ if RUBY_VERSION < "1.9"
20
+ STDERR.print("Ruby version is too old\n")
21
+ exit(1)
22
+ end
23
+
24
+ hdrs = if RUBY_VERSION == '1.9.2'
25
+ lambda {
26
+ have_struct_member("rb_method_entry_t", "body", "method.h")
27
+ have_header("vm_core.h") and have_header("iseq.h") and have_header("insns.inc") and
28
+ have_header("insns_info.inc") and have_header("eval_intern.h")
29
+ }
30
+ elsif RUBY_VERSION == '1.9.3'
31
+ lambda {
32
+ iseqs = %w[vm_core.h iseq.h]
33
+ begin
34
+ have_struct_member("rb_method_entry_t", "called_id", "method.h") or
35
+ have_struct_member("rb_control_frame_t", "method_id", "method.h")
36
+ end and
37
+ have_header("vm_core.h") and have_header("iseq.h") and have_header("insns.inc") and
38
+ have_header("insns_info.inc") and have_header("eval_intern.h") or return(false)
39
+ have_type("struct iseq_line_info_entry", iseqs) or
40
+ have_type("struct iseq_insn_info_entry", iseqs) or
41
+ return(false)
42
+ if checking_for(checking_message("if rb_iseq_compile_with_option was added an argument filepath")) do
43
+ try_compile(<<SRC)
44
+ #include <ruby.h>
45
+ #include "vm_core.h"
46
+ extern VALUE rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath);
47
+ SRC
48
+ end
49
+ $defs << '-DRB_ISEQ_COMPILE_5ARGS'
50
+ end
51
+ }
52
+ elsif RUBY_VERSION == '2.0.0'
53
+ lambda {
54
+ iseqs = %w[vm_core.h iseq.h]
55
+ begin
56
+ have_struct_member("rb_method_entry_t", "called_id", "method.h") or
57
+ have_struct_member("rb_control_frame_t", "method_id", "method.h")
58
+ end and
59
+ have_header("vm_core.h") and have_header("iseq.h") and have_header("insns.inc") and
60
+ have_header("insns_info.inc") and have_header("eval_intern.h") or return(false)
61
+ have_type("struct iseq_line_info_entry", iseqs) or
62
+ have_type("struct iseq_insn_info_entry", iseqs) or
63
+ return(false)
64
+ if checking_for(checking_message("if rb_iseq_compile_with_option was added an argument filepath")) do
65
+ try_compile(<<SRC)
66
+ #include <ruby.h>
67
+ #include "vm_core.h"
68
+ extern VALUE rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath);
69
+ SRC
70
+ end
71
+ $defs << "-DHAVE_RB_ISEQ_COMPILE_ON_BASE -DVM_DEBUG_BP_CHECK -DHAVE_RB_CONTROL_FRAME_T_EP -DHAVE_RB_ISEQ_T_LOCATION -DHAVE_RB_ISEQ_T_LINE_INFO_SIZE "
72
+ end
73
+ }
74
+ else
75
+ STDERR.puts "Ruby version #{RUBY_VERSION} is not supported."
76
+ exit(1)
77
+ end
78
+
79
+
80
+ header_dir = RUBY_VERSION.gsub('.', '')
81
+ current_dir = File.dirname(__FILE__)
82
+ %w{ruby_debug.h ruby_debug.c breakpoint.c}.each do |file|
83
+ FileUtils.cp("#{current_dir}/#{header_dir}/#{file}", current_dir)
84
+ end
85
+
86
+ dir_config("ruby")
87
+ if !Debugger::RubyCoreSource.create_makefile_with_core(hdrs, "ruby_debug")
88
+ STDERR.print("Makefile creation failed\n")
89
+ STDERR.print("*************************************************************\n\n")
90
+ STDERR.print(" NOTE: If your headers were not found, try passing\n")
91
+ STDERR.print(" --with-ruby-include=PATH_TO_HEADERS \n\n")
92
+ STDERR.print("*************************************************************\n\n")
93
+ exit(1)
94
+ end
@@ -0,0 +1,5 @@
1
+ module Debugger
2
+ end
3
+
4
+ require 'ruby-debug'
5
+ require 'debugger/version'
@@ -0,0 +1,5 @@
1
+ module Debugger
2
+ # TODO: remove version from C ext
3
+ send :remove_const, :VERSION if const_defined? :VERSION
4
+ VERSION = '1.4.0'
5
+ end
@@ -0,0 +1,305 @@
1
+ require 'ruby_debug.so'
2
+ require 'linecache19'
3
+
4
+ module Debugger
5
+
6
+ # Default options to Debugger.start
7
+ DEFAULT_START_SETTINGS = {
8
+ :init => true, # Set $0 and save ARGV?
9
+ :post_mortem => false, # post-mortem debugging on uncaught exception?
10
+ :tracing => nil # Debugger.tracing value. true/false resets,
11
+ # nil keeps the prior value
12
+ } unless defined?(DEFAULT_START_SETTINGS)
13
+
14
+ class Context
15
+ def interrupt
16
+ self.stop_next = 1
17
+ end
18
+
19
+ alias __c_frame_binding frame_binding
20
+ def frame_binding(frame)
21
+ __c_frame_binding(frame) || hbinding(frame)
22
+ end
23
+
24
+ private
25
+
26
+ def hbinding(frame)
27
+ hash = frame_locals(frame)
28
+ code = hash.keys.map{|k| "#{k} = hash['#{k}']" unless k=='self' }.compact.join(';') + ';binding'
29
+ if obj = frame_self(frame)
30
+ obj.instance_eval code
31
+ else
32
+ eval code, TOPLEVEL_BINDING
33
+ end
34
+ end
35
+
36
+ def handler
37
+ Debugger.handler or raise 'No interface loaded'
38
+ end
39
+
40
+ def at_breakpoint(breakpoint)
41
+ handler.at_breakpoint(self, breakpoint)
42
+ end
43
+
44
+ def at_catchpoint(excpt)
45
+ handler.at_catchpoint(self, excpt)
46
+ end
47
+
48
+ def at_tracing(file, line)
49
+ @tracing_started = File.identical?(file, Debugger::PROG_SCRIPT)
50
+ handler.at_tracing(self, file, line) if @tracing_started
51
+ end
52
+
53
+ def at_line(file, line)
54
+ handler.at_line(self, file, line)
55
+ end
56
+
57
+ def at_return(file, line)
58
+ handler.at_return(self, file, line)
59
+ end
60
+ end
61
+
62
+ @reload_source_on_change = false
63
+ @tracing_started = false
64
+
65
+ class << self
66
+ # interface modules provide +handler+ object
67
+ attr_accessor :handler
68
+
69
+ # if <tt>true</tt>, checks the modification time of source files and reloads if it was modified
70
+ attr_accessor :reload_source_on_change
71
+
72
+ attr_accessor :last_exception
73
+ Debugger.last_exception = nil
74
+
75
+ #
76
+ # Interrupts the current thread
77
+ #
78
+ def interrupt
79
+ current_context.interrupt
80
+ end
81
+
82
+ #
83
+ # Interrupts the last debugged thread
84
+ #
85
+ def interrupt_last
86
+ if context = last_context
87
+ return nil unless context.thread.alive?
88
+ context.interrupt
89
+ end
90
+ context
91
+ end
92
+
93
+ def source_reload
94
+ Object.send(:remove_const, "SCRIPT_LINES__") if Object.const_defined?("SCRIPT_LINES__")
95
+ Object.const_set("SCRIPT_LINES__", {})
96
+ LineCache::clear_file_cache
97
+ end
98
+
99
+ # Get line +line_number+ from file named +filename+. Return "\n"
100
+ # there was a problem. Leaking blanks are stripped off.
101
+ def line_at(filename, line_number) # :nodoc:
102
+ @reload_on_change=nil unless defined?(@reload_on_change)
103
+ line = LineCache::getline(filename, line_number, @reload_on_change)
104
+ return "\n" unless line
105
+ return "#{line.gsub(/^\s+/, '').chomp}\n"
106
+ end
107
+
108
+ #
109
+ # Activates the post-mortem mode. There are two ways of using it:
110
+ #
111
+ # == Global post-mortem mode
112
+ # By calling Debugger.post_mortem method without a block, you install
113
+ # at_exit hook that intercepts any unhandled by your script exceptions
114
+ # and enables post-mortem mode.
115
+ #
116
+ # == Local post-mortem mode
117
+ #
118
+ # If you know that a particular block of code raises an exception you can
119
+ # enable post-mortem mode by wrapping this block with Debugger.post_mortem, e.g.
120
+ #
121
+ # def offender
122
+ # raise 'error'
123
+ # end
124
+ # Debugger.post_mortem do
125
+ # ...
126
+ # offender
127
+ # ...
128
+ # end
129
+ def post_mortem
130
+ if block_given?
131
+ old_post_mortem = self.post_mortem?
132
+ begin
133
+ self.post_mortem = true
134
+ yield
135
+ rescue Exception => exp
136
+ handle_post_mortem(exp)
137
+ raise
138
+ ensure
139
+ self.post_mortem = old_post_mortem
140
+ end
141
+ else
142
+ return if post_mortem?
143
+ self.post_mortem = true
144
+ debug_at_exit do
145
+ handle_post_mortem($!) if $! && post_mortem?
146
+ end
147
+ end
148
+ end
149
+
150
+ def handle_post_mortem(exp)
151
+ return if !exp || !exp.__debug_context ||
152
+ exp.__debug_context.stack_size == 0
153
+ Debugger.suspend
154
+ orig_tracing = Debugger.tracing, Debugger.current_context.tracing
155
+ Debugger.tracing = Debugger.current_context.tracing = false
156
+ Debugger.last_exception = exp
157
+ handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line)
158
+ ensure
159
+ Debugger.tracing, Debugger.current_context.tracing = orig_tracing
160
+ Debugger.resume
161
+ end
162
+ # private :handle_post_mortem
163
+ end
164
+
165
+ class DebugThread # :nodoc:
166
+ end
167
+
168
+ class ThreadsTable # :nodoc:
169
+ end
170
+
171
+ # Debugger.start(options) -> bool
172
+ # Debugger.start(options) { ... } -> obj
173
+ #
174
+ # If it's called without a block it returns +true+, unless debugger
175
+ # was already started. If a block is given, it starts debugger and
176
+ # yields to block. When the block is finished executing it stops
177
+ # the debugger with Debugger.stop method.
178
+ #
179
+ # If a block is given, it starts debugger and yields to block. When
180
+ # the block is finished executing it stops the debugger with
181
+ # Debugger.stop method. Inside the block you will probably want to
182
+ # have a call to Debugger.debugger. For example:
183
+ #
184
+ # Debugger.start{debugger; foo} # Stop inside of foo
185
+ #
186
+ # Also, ruby-debug only allows
187
+ # one invocation of debugger at a time; nested Debugger.start's
188
+ # have no effect and you can't use this inside the debugger itself.
189
+ #
190
+ # <i>Note that if you want to stop debugger, you must call
191
+ # Debugger.stop as many time as you called Debugger.start
192
+ # method.</i>
193
+ #
194
+ # +options+ is a hash used to set various debugging options.
195
+ # Set :init true if you want to save ARGV and some variables which
196
+ # make a debugger restart possible. Only the first time :init is set true
197
+ # will values get set. Since ARGV is saved, you should make sure
198
+ # it hasn't been changed before the (first) call.
199
+ # Set :post_mortem true if you want to enter post-mortem debugging
200
+ # on an uncaught exception. Once post-mortem debugging is set, it can't
201
+ # be unset.
202
+ def start(options={}, &block)
203
+ options = Debugger::DEFAULT_START_SETTINGS.merge(options)
204
+ if options[:init]
205
+ Debugger.const_set('ARGV', ARGV.clone) unless
206
+ defined? Debugger::ARGV
207
+ Debugger.const_set('PROG_SCRIPT', $0) unless
208
+ defined? Debugger::PROG_SCRIPT
209
+ Debugger.const_set('INITIAL_DIR', Dir.pwd) unless
210
+ defined? Debugger::INITIAL_DIR
211
+ end
212
+ Debugger.tracing = options[:tracing] unless options[:tracing].nil?
213
+ retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block)
214
+ if options[:post_mortem]
215
+ post_mortem
216
+ end
217
+ return retval
218
+ end
219
+ module_function :start
220
+ end
221
+
222
+ module Kernel
223
+
224
+ # Enters the debugger in the current thread after _steps_ line events occur.
225
+ # Before entering the debugger startup script is read.
226
+ #
227
+ # Setting _steps_ to 0 will cause a break in the debugger subroutine
228
+ # and not wait for a line event to occur. You will have to go "up 1"
229
+ # in order to be back in your debugged program rather than the
230
+ # debugger. Settings _steps_ to 0 could be useful you want to stop
231
+ # right after the last statement in some scope, because the next
232
+ # step will take you out of some scope.
233
+
234
+ # If a block is given (and the debugger hasn't been started, we run the
235
+ # block under the debugger. Alas, when a block is given, we can't support
236
+ # running the startup script or support the steps option. FIXME.
237
+ def debugger(steps = 1, &block)
238
+ if block
239
+ Debugger.start({}, &block)
240
+ else
241
+ Debugger.start unless Debugger.started?
242
+ Debugger.run_init_script(StringIO.new)
243
+ if 0 == steps
244
+ Debugger.current_context.stop_frame = 0
245
+ else
246
+ Debugger.current_context.stop_next = steps
247
+ end
248
+ end
249
+ end
250
+ alias breakpoint debugger unless respond_to?(:breakpoint)
251
+
252
+ #
253
+ # Returns a binding of n-th call frame
254
+ #
255
+ def binding_n(n = 0)
256
+ Debugger.skip do
257
+ if RUBY_VERSION < "1.9"
258
+ Debugger.current_context.frame_binding(n+2)
259
+ else
260
+ Debugger.current_context.frame_binding(n+1)
261
+ end
262
+ end
263
+ end
264
+ end
265
+
266
+ class Exception # :nodoc:
267
+ attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
268
+ end
269
+
270
+ class Module
271
+ #
272
+ # Wraps the +meth+ method with Debugger.start {...} block.
273
+ #
274
+ def debug_method(meth)
275
+ old_meth = "__debugee_#{meth}"
276
+ old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
277
+ alias_method old_meth.to_sym, meth
278
+ class_eval <<-EOD
279
+ def #{meth}(*args, &block)
280
+ Debugger.start do
281
+ debugger 2
282
+ #{old_meth}(*args, &block)
283
+ end
284
+ end
285
+ EOD
286
+ end
287
+
288
+ #
289
+ # Wraps the +meth+ method with Debugger.post_mortem {...} block.
290
+ #
291
+ def post_mortem_method(meth)
292
+ old_meth = "__postmortem_#{meth}"
293
+ old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
294
+ alias_method old_meth.to_sym, meth
295
+ class_eval <<-EOD
296
+ def #{meth}(*args, &block)
297
+ Debugger.start do |dbg|
298
+ dbg.post_mortem do
299
+ #{old_meth}(*args, &block)
300
+ end
301
+ end
302
+ end
303
+ EOD
304
+ end
305
+ end