ruby-debug 0.1.5-mswin32 → 0.2-mswin32

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,10 @@
1
+ 0.2 (2006-06-17)
2
+ - Added the remote debugging. It should be activated by calling Debugger#start_server method.
3
+ - CHANGED: In order to activate the debugger, it's not enough to require 'ruby-debug'.
4
+ Debugger#start method must be called explicitly.
5
+ - Debugger used to evaluate anything you enter as long as it's not a command. Starting from
6
+ this version the 'eval' command must be used to evaluate an expression.
7
+
1
8
  0.1.5 (2006-06-13)
2
9
  - Now the check for a breakpoint uses base filename of the source file.
3
10
  - Removed compilation warnings when compiling with -Wall
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/rdoctask'
5
5
  SO_NAME = "ruby_debug.so"
6
6
 
7
7
  # ------- Default Package ----------
8
- RUBY_DEBUG_VERSION = "0.1.5"
8
+ RUBY_DEBUG_VERSION = "0.2"
9
9
 
10
10
  FILES = FileList[
11
11
  'Rakefile',
data/bin/rdebug CHANGED
@@ -1,13 +1,84 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- if ARGV.empty?
4
- puts "Usage: #{__FILE__} <script>"
5
- exit(1)
6
- end
7
-
8
3
  require 'rubygems'
4
+ require 'optparse'
5
+ require "ostruct"
9
6
  require 'ruby-debug'
10
- trap('INT') { Debugger.interrupt_last }
11
7
 
12
- debugger 2
13
- load ARGV.shift
8
+ options = OpenStruct.new(
9
+ 'server' => false,
10
+ 'client' => false,
11
+ 'host' => nil,
12
+ 'port' => Debugger::PORT
13
+ )
14
+
15
+ opts = OptionParser.new do |opts|
16
+ opts.banner = <<EOB
17
+ ruby-debug #{Debugger::VERSION}
18
+ Usage: rdebug [options] <script.rb> <script.rb parameters>
19
+ EOB
20
+ opts.separator ""
21
+ opts.separator "Options:"
22
+ opts.on("-s", "--server", "Listen for remote connections") {options.server = true}
23
+ opts.on("-c", "--client", "Connect to remote debugger") {options.client = true}
24
+ opts.on("-h", "--host HOST", "Host name used for remote debugging") {|options.host|}
25
+ opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|options.port|}
26
+ opts.separator ""
27
+ opts.separator "Common options:"
28
+ opts.on_tail("--help", "Show this message") do
29
+ puts opts
30
+ exit
31
+ end
32
+ opts.on_tail("-v", "--version", "Show version") do
33
+ puts "ruby-debug #{Debugger::VERSION}"
34
+ exit
35
+ end
36
+ end
37
+
38
+ begin
39
+ opts.parse! ARGV
40
+ rescue StandardError => e
41
+ puts opts
42
+ puts
43
+ puts e.message
44
+ exit(-1)
45
+ end
46
+
47
+ if options.client
48
+ require "socket"
49
+ interface = Debugger::LocalInterface.new
50
+ socket = TCPSocket.new(options.host, options.port)
51
+ puts "Connected."
52
+
53
+ catch(:exit) do
54
+ while (line = socket.gets)
55
+ case line
56
+ when /^PROMPT (.*)$/
57
+ input = interface.read_command($1)
58
+ throw :exit unless input
59
+ socket.puts input
60
+ when /^CONFIRM (.*)$/
61
+ input = interface.confirm($1)
62
+ throw :exit unless input
63
+ socket.puts input
64
+ else
65
+ print line
66
+ end
67
+ end
68
+ end
69
+ socket.close
70
+ puts
71
+ else
72
+ if ARGV.empty?
73
+ puts opts
74
+ puts
75
+ puts "Must specify a script to run"
76
+ exit(-1)
77
+ end
78
+
79
+ trap('INT') { Debugger.interrupt_last }
80
+ Debugger.start_server(options.host, options.port) if options.server
81
+ Debugger.start
82
+ debugger 2
83
+ load ARGV.shift
84
+ end
data/bin/remote ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'socket'
4
+ require "ruby-debug/inputs"
5
+
6
+ host = ARGV[0] || "localhost"
7
+ port = 8989
8
+
9
+ input = Debugger::LocalInput.new
10
+ socket = TCPSocket.new(host, port)
11
+ puts "Connected."
12
+
13
+ catch(:exit) do
14
+ while (line = socket.gets)
15
+ case line
16
+ when /^PROMPT (.*)$/
17
+ data = input.read_command($1)
18
+ throw :exit unless data
19
+ socket.puts data
20
+ when /^CONFIRM (.*)$/
21
+ data = input.confirm($1)
22
+ throw :exit unless data
23
+ socket.puts data
24
+ else
25
+ print line
26
+ end
27
+ end
28
+ end
29
+ socket.close
30
+ puts
data/ext/ruby_debug.c CHANGED
@@ -4,13 +4,15 @@
4
4
  #include <rubysig.h>
5
5
  #include <st.h>
6
6
 
7
- #define DEBUG_VERSION "0.1.5"
7
+ #define DEBUG_VERSION "0.2"
8
8
 
9
9
  typedef struct {
10
10
  int thnum;
11
+ VALUE last_file;
12
+ VALUE last_line;
13
+ int moved;
11
14
  int stop_next;
12
15
  int dest_frame;
13
- int src_line;
14
16
  int stop_line;
15
17
  int stop_frame;
16
18
  int suspend;
@@ -43,7 +45,7 @@ static VALUE cContext;
43
45
  static VALUE cFrame;
44
46
  static VALUE cBreakpoint;
45
47
 
46
- static ID idDebugCommand;
48
+ static ID idAtLine;
47
49
  static ID idAtBreakpoint;
48
50
  static ID idAtCatchpoint;
49
51
  static ID idAtTracing;
@@ -81,6 +83,8 @@ debug_context_mark(void* data)
81
83
  debug_context_t *debug_context = (debug_context_t *)data;
82
84
  rb_gc_mark(debug_context->frames);
83
85
  rb_gc_mark(debug_context->thread);
86
+ rb_gc_mark(debug_context->last_file);
87
+ rb_gc_mark(debug_context->last_line);
84
88
  }
85
89
 
86
90
  static VALUE
@@ -91,9 +95,13 @@ debug_context_create(VALUE thread)
91
95
 
92
96
  debug_context = ALLOC(debug_context_t);
93
97
  debug_context-> thnum = ++thnum_max;
98
+
99
+ debug_context->last_file = Qnil;
100
+ debug_context->last_line = Qnil;
101
+ debug_context->moved = 0;
102
+
94
103
  debug_context->stop_next = -1;
95
104
  debug_context->dest_frame = -1;
96
- debug_context->src_line = -1;
97
105
  debug_context->stop_line = -1;
98
106
  debug_context->stop_frame = -1;
99
107
  debug_context->suspend = 0;
@@ -145,16 +153,36 @@ debug_frame_create(VALUE file, VALUE line, VALUE binding, ID id)
145
153
  return result;
146
154
  }
147
155
 
148
- static VALUE
149
- call_debug_command(VALUE context, int thnum, VALUE binding, ID mid, VALUE file, VALUE line)
156
+ static void
157
+ save_current_position(VALUE context)
150
158
  {
151
- VALUE id;
159
+ VALUE cur_frame;
160
+ debug_context_t *debug_context;
161
+ debug_frame_t *debug_frame;
162
+
163
+ Data_Get_Struct(context, debug_context_t, debug_context);
164
+ if(RARRAY(debug_context->frames)->len == 0)
165
+ return;
166
+
167
+ cur_frame = *RARRAY(debug_context->frames)->ptr;
168
+ Data_Get_Struct(cur_frame, debug_frame_t, debug_frame);
169
+
170
+ debug_context->last_file = debug_frame->file;
171
+ debug_context->last_line = debug_frame->line;
172
+ debug_context->moved = 0;
173
+ }
152
174
 
153
- id = mid ? ID2SYM(mid) : Qnil;
175
+ #define did_moved() (debug_context->last_line != line || \
176
+ debug_context->last_file == Qnil || \
177
+ rb_str_cmp(debug_context->last_file, file) != 0)
154
178
 
179
+ static VALUE
180
+ call_at_line(VALUE context, int thnum, VALUE binding, VALUE file, VALUE line)
181
+ {
155
182
  last_debugged_thnum = thnum;
183
+ save_current_position(context);
156
184
  debug_suspend(mDebugger);
157
- return rb_funcall(context, idDebugCommand, 4, file, line, id, binding);
185
+ return rb_funcall(context, idAtLine, 3, file, line, binding);
158
186
  }
159
187
 
160
188
  static void
@@ -189,7 +217,7 @@ basename(VALUE filename)
189
217
  }
190
218
 
191
219
  static int
192
- check_breakpoints(VALUE context, VALUE file, VALUE klass, VALUE pos)
220
+ check_breakpoints(debug_context_t *debug_context, VALUE file, VALUE klass, VALUE pos)
193
221
  {
194
222
  VALUE breakpoint;
195
223
  debug_breakpoint_t *debug_breakpoint;
@@ -197,6 +225,9 @@ check_breakpoints(VALUE context, VALUE file, VALUE klass, VALUE pos)
197
225
 
198
226
  if(RARRAY(breakpoints)->len == 0)
199
227
  return -1;
228
+ if(!debug_context->moved)
229
+ return -1;
230
+
200
231
  for(i = 0; i < RARRAY(breakpoints)->len; i++)
201
232
  {
202
233
  breakpoint = rb_ary_entry(breakpoints, i);
@@ -282,10 +313,12 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
282
313
  debug_context_t *debug_context;
283
314
  VALUE file = Qnil, line = Qnil;
284
315
  int breakpoint_index = -1;
285
-
316
+
286
317
  static int debugging = 0;
287
318
 
319
+ if (mid == ID_ALLOCATOR) return;
288
320
  if(debugging) return;
321
+ if(!node) return;
289
322
 
290
323
  debugging++;
291
324
 
@@ -294,11 +327,11 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
294
327
  Data_Get_Struct(context, debug_context_t, debug_context);
295
328
  check_suspend(debug_context);
296
329
 
297
- if(node)
298
- {
299
- file = rb_str_new2(node->nd_file);
300
- line = INT2FIX(nd_line(node));
301
- }
330
+ file = rb_str_new2(node->nd_file);
331
+ line = INT2FIX(nd_line(node));
332
+
333
+ if(did_moved())
334
+ debug_context->moved = 1;
302
335
 
303
336
  switch(event)
304
337
  {
@@ -310,15 +343,15 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
310
343
  {
311
344
  rb_funcall(context, idAtTracing, 2, file, line);
312
345
  }
313
-
346
+
314
347
  if(debug_context->dest_frame == -1 ||
315
348
  RARRAY(debug_context->frames)->len == debug_context->dest_frame)
316
349
  {
317
350
  debug_context->stop_next--;
318
351
  if(debug_context->stop_next < 0)
319
- debug_context->stop_next = -1;
352
+ debug_context->stop_next = -1;
320
353
  /* we check that we actualy moved to another line */
321
- if(line != Qnil && debug_context->src_line != FIX2INT(line))
354
+ if(did_moved())
322
355
  {
323
356
  debug_context->stop_line--;
324
357
  }
@@ -334,7 +367,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
334
367
  }
335
368
 
336
369
  if(debug_context->stop_next == 0 || debug_context->stop_line == 0 ||
337
- (breakpoint_index = check_breakpoints(context, file, klass, line)) != -1)
370
+ (breakpoint_index = check_breakpoints(debug_context, file, klass, line)) != -1)
338
371
  {
339
372
  binding = self? create_binding(self) : Qnil;
340
373
  /* check breakpoint expression */
@@ -342,41 +375,37 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
342
375
  {
343
376
  breakpoint = get_breakpoint_at(breakpoint_index);
344
377
  if(check_breakpoint_expression(breakpoint, binding))
345
- rb_funcall(context, idAtBreakpoint, 2, breakpoint, mid ? rb_str_new2(rb_id2name(mid)) : Qnil);
378
+ rb_funcall(context, idAtBreakpoint, 1, breakpoint);
346
379
  else
347
380
  break;
348
381
  }
349
382
 
350
383
  /* reset all pointers */
351
384
  debug_context->dest_frame = -1;
352
- debug_context->src_line = -1;
353
385
  debug_context->stop_line = -1;
354
386
  debug_context->stop_next = -1;
355
387
 
356
- call_debug_command(context, debug_context->thnum, binding, mid, file, line);
388
+ call_at_line(context, debug_context->thnum, binding, file, line);
357
389
  }
358
390
  break;
359
391
  }
360
392
  case RUBY_EVENT_C_CALL:
361
- {
362
- if(node)
363
393
  {
364
394
  set_frame_source(debug_context, file, line);
365
- }
366
- break;
395
+ break;
367
396
  }
368
397
  case RUBY_EVENT_CALL:
369
398
  {
370
399
  save_call_frame(self, file, line, mid, debug_context);
371
- breakpoint_index = check_breakpoints(context, file, klass, rb_str_new2(rb_id2name(mid)));
400
+ breakpoint_index = check_breakpoints(debug_context, file, klass, rb_str_new2(rb_id2name(mid)));
372
401
  if(breakpoint_index != -1)
373
402
  {
374
403
  binding = self? create_binding(self) : Qnil;
375
404
  breakpoint = get_breakpoint_at(breakpoint_index);
376
405
  if(check_breakpoint_expression(breakpoint, binding))
377
406
  {
378
- rb_funcall(context, idAtBreakpoint, 2, breakpoint, mid ? rb_str_new2(rb_id2name(mid)) : Qnil);
379
- call_debug_command(context, debug_context->thnum, binding, mid, file, line);
407
+ rb_funcall(context, idAtBreakpoint, 1, breakpoint);
408
+ call_at_line(context, debug_context->thnum, binding, file, line);
380
409
  }
381
410
  }
382
411
  break;
@@ -407,7 +436,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
407
436
  if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) )
408
437
  {
409
438
  debug_stop(mDebugger);
410
- rb_exit(0);
439
+ break;
411
440
  }
412
441
 
413
442
  if(catchpoint == Qnil)
@@ -419,10 +448,10 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
419
448
  aclass = rb_ary_entry(ancestors, i);
420
449
  if(rb_str_cmp(rb_mod_name(aclass), catchpoint) == 0)
421
450
  {
422
- rb_funcall(context, idAtCatchpoint, 0);
451
+ rb_funcall(context, idAtCatchpoint, 1, ruby_errinfo);
423
452
  binding = self? create_binding(self) : Qnil;
424
- call_debug_command(context, debug_context->thnum, binding, mid, file, line);
425
- break;
453
+ call_at_line(context, debug_context->thnum, binding, file, line);
454
+ break;
426
455
  }
427
456
  }
428
457
 
@@ -437,18 +466,6 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
437
466
  debugging--;
438
467
  }
439
468
 
440
- static VALUE
441
- debug_thnum(VALUE self)
442
- {
443
- VALUE thread, context;
444
- debug_context_t *debug_context;
445
-
446
- thread = rb_thread_current();
447
- context = thread_context_lookup(thread);
448
- Data_Get_Struct(context, debug_context_t, debug_context);
449
- return INT2FIX(debug_context->thnum);
450
- }
451
-
452
469
  static VALUE
453
470
  debug_start(VALUE self)
454
471
  {
@@ -743,9 +760,8 @@ context_stop_next(VALUE self, VALUE steps)
743
760
  static VALUE
744
761
  context_step_over(int argc, VALUE *argv, VALUE self)
745
762
  {
746
- VALUE lines, frame, cur_frame;
763
+ VALUE lines, frame;
747
764
  debug_context_t *debug_context;
748
- debug_frame_t *debug_frame;
749
765
 
750
766
  debug_check_started();
751
767
 
@@ -766,10 +782,6 @@ context_step_over(int argc, VALUE *argv, VALUE self)
766
782
  debug_context->dest_frame = FIX2INT(frame);
767
783
  }
768
784
 
769
- cur_frame = *RARRAY(debug_context->frames)->ptr;
770
- Data_Get_Struct(cur_frame, debug_frame_t, debug_frame);
771
- debug_context->src_line = FIX2INT(debug_frame->line);
772
-
773
785
  return Qnil;
774
786
  }
775
787
 
@@ -937,7 +949,6 @@ Init_ruby_debug()
937
949
  rb_define_module_function(mDebugger, "start", debug_start, 0);
938
950
  rb_define_module_function(mDebugger, "stop", debug_stop, 0);
939
951
  rb_define_module_function(mDebugger, "started?", debug_is_started, 0);
940
- rb_define_module_function(mDebugger, "thnum", debug_thnum, 0);
941
952
  rb_define_module_function(mDebugger, "breakpoints", debug_breakpoints, 0);
942
953
  rb_define_module_function(mDebugger, "add_breakpoint", debug_add_breakpoint, -1);
943
954
  rb_define_module_function(mDebugger, "catchpoint", debug_catchpoint, 0);
@@ -974,7 +985,7 @@ Init_ruby_debug()
974
985
  rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
975
986
  rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
976
987
 
977
- idDebugCommand = rb_intern("debug_command");
988
+ idAtLine = rb_intern("at_line");
978
989
  idAtBreakpoint = rb_intern("at_breakpoint");
979
990
  idAtCatchpoint = rb_intern("at_catchpoint");
980
991
  idAtTracing = rb_intern("at_tracing");
data/lib/ruby-debug.rb CHANGED
@@ -1,10 +1,13 @@
1
- require 'ruby_debug.so'
2
1
  require 'pp'
2
+ require 'stringio'
3
+ require 'thread'
4
+ require 'ruby_debug.so'
5
+ require 'ruby-debug/processor'
3
6
 
4
7
  SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
5
8
 
6
9
  module Debugger
7
- class Mutex
10
+ MUTEX = Class.new do
8
11
  def initialize
9
12
  @locker = nil
10
13
  @waiting = []
@@ -42,582 +45,56 @@ module Debugger
42
45
  t.run if t
43
46
  self
44
47
  end
45
- end
46
-
47
- MUTEX = Mutex.new
48
-
49
- @stdout = STDOUT
50
- @display = []
51
- @trace_proc = nil
48
+ end.new
49
+
50
+ PORT = 8989
52
51
 
52
+ @processor = CommandProcessor.new
53
+
53
54
  class Context
54
- DEBUG_LAST_CMD = []
55
-
56
55
  private
57
56
 
58
- begin
59
- require 'readline'
60
- def readline(prompt, hist)
61
- Readline::readline(prompt, hist)
62
- end
63
- rescue LoadError
64
- def readline(prompt, hist)
65
- STDOUT.print prompt
66
- STDOUT.flush
67
- line = STDIN.gets
68
- exit unless line
69
- line.chomp!
70
- line
71
- end
72
- USE_READLINE = false
57
+ def processor
58
+ Debugger.processor
73
59
  end
74
60
 
75
- def stdout
76
- Debugger.stdout
61
+ def at_breakpoint(breakpoint)
62
+ processor.at_breakpoint(self, breakpoint)
77
63
  end
78
64
 
79
- def at_breakpoint(breakpoint, method_name)
80
- n = Debugger.breakpoints.index(breakpoint) + 1
81
- stdout.printf "Breakpoint %d, %s at %s:%s\n", n, method_name, breakpoint.source, breakpoint.pos
82
- end
83
-
84
- def at_catchpoint
85
- frames = Debugger.current_context.frames
86
- stdout.printf "%s:%d: `%s' (%s)\n", frames[0].file, frames[0].line, $!, $!.class
87
- fs = frames.size
88
- tb = caller(0)[-fs..-1]
89
- if tb
90
- for i in tb
91
- stdout.printf "\tfrom %s\n", i
92
- end
93
- end
65
+ def at_catchpoint(excpt)
66
+ processor.at_catchpoint(self, excpt)
94
67
  end
95
68
 
96
69
  def at_tracing(file, line)
97
- if Debugger.trace_proc
98
- Debugger.trace_proc.call(self.thnum, file, line)
99
- else
100
- stdout.puts sprintf("Tracing(%d):%s:%s %s", self.thnum, file, line, line_at(file, line))
101
- end
70
+ processor.at_tracing(self, file, line)
102
71
  end
103
72
 
104
- def debug_command(file, line, id, binding)
73
+ def at_line(file, line, binding)
105
74
  MUTEX.lock
106
- frame_pos = 0
107
- binding_file = file
108
- binding_line = line
109
- previous_line = nil
110
- stdout.printf "%s:%d: %s", binding_file, binding_line, line_at(binding_file, binding_line)
111
- display_expressions(binding)
112
- prompt = true
113
- while prompt and input = readline("(rdb:%d) " % Debugger.thnum, true)
114
- catch(:debug_error) do
115
- if input == ""
116
- next unless DEBUG_LAST_CMD[0]
117
- input = DEBUG_LAST_CMD[0]
118
- else
119
- DEBUG_LAST_CMD[0] = input
120
- end
121
-
122
- case input
123
- when /^\s*s(?:tep)?(?:\s+(\d+))?$/
124
- self.stop_next = $1 ? $1.to_i : 1
125
- prompt = false
126
-
127
- when /^\s*c(?:ont)?$|^\s*r(?:un)?$/
128
- prompt = false
129
-
130
- when /^\s*v(?:ar)?\s+/
131
- debug_variable_info($', binding)
132
-
133
- when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
134
- display_frames(frame_pos)
135
-
136
- when /^\s*l(?:ist)?(?:\s+(.+))?$/
137
- if not $1
138
- b = previous_line ? previous_line + 10 : binding_line - 5
139
- e = b + 9
140
- elsif $1 == '-'
141
- b = previous_line ? previous_line - 10 : binding_line - 5
142
- e = b + 9
143
- else
144
- b, e = $1.split(/[-,]/)
145
- if e
146
- b = b.to_i
147
- e = e.to_i
148
- else
149
- b = b.to_i - 5
150
- e = b + 9
151
- end
152
- end
153
- previous_line = b
154
- display_list(b, e, binding_file, binding_line)
155
-
156
- when /^\s*n(?:ext)?(?:\s+(\d+))?$/
157
- steps = $1 ? $1.to_i : 1
158
- self.step_over steps, self.frames.size - frame_pos
159
- prompt = false
160
-
161
- when /^\s*up(?:\s+(\d+))?$/
162
- previous_line = nil
163
- frame_pos += $1 ? $1.to_i : 1
164
- if frame_pos >= self.frames.size
165
- frame_pos = self.frames.size - 1
166
- stdout.puts "At toplevel"
167
- end
168
- frame = self.frames[frame_pos]
169
- binding, binding_file, binding_line = frame.binding, frame.file, frame.line
170
- stdout.print format_frame(frame, frame_pos)
171
-
172
- when /^\s*down(?:\s+(\d+))?$/
173
- previous_line = nil
174
- frame_pos -= $1 ? $1.to_i : 1
175
- if frame_pos < 0
176
- frame_pos = 0
177
- stdout.print "At stack bottom\n"
178
- end
179
- frame = self.frames[frame_pos]
180
- binding, binding_file, binding_line = frame.binding, frame.file, frame.line
181
- stdout.print format_frame(frame, frame_pos)
182
-
183
- when /^\s*fin(?:ish)?$/
184
- if frame_pos == self.frames.size
185
- stdout.print "\"finish\" not meaningful in the outermost frame.\n"
186
- else
187
- self.stop_frame = self.frames.size - frame_pos
188
- frame_pos = 0
189
- prompt = false
190
- end
191
-
192
- when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:\s]+)\s*(?:\sif\s+(.+))?$/
193
- pos = $2
194
- expr = $3
195
- if $1
196
- klass = debug_silent_eval($1, binding)
197
- if klass && !klass.kind_of?(Module)
198
- stdout.puts "Unknown class #$1"
199
- throw :debug_error
200
- end
201
- klass = klass.name if klass
202
- file = $1
203
- end
204
- if pos =~ /^\d+$/
205
- pname = pos
206
- pos = pos.to_i
207
- else
208
- pname = pos = pos.intern.id2name
209
- end
210
- Debugger.add_breakpoint klass || file, pos, expr
211
- stdout.printf "Set breakpoint %d at %s:%s\n", Debugger.breakpoints.size, klass || file, pname
212
-
213
- when /^\s*b(?:reak)?\s+(.+)[#.]([^.:\s]+)(?:\s+if\s+(.+))?$/
214
- pos = $2.intern.id2name
215
- expr = $3
216
- klass = debug_eval($1, binding)
217
- if klass.nil? || !klass.kind_of?(Module)
218
- stdout.puts "Unknown class #$1"
219
- throw :debug_error
220
- end
221
- Debugger.add_breakpoint klass.name, pos, expr
222
- stdout.printf "Set breakpoint %d at %s.%s\n", Debugger.breakpoints.size, klass, pos
223
-
224
- when /^\s*b(?:reak)?$/
225
- unless Debugger.breakpoints.empty?
226
- stdout.print "Breakpoints:\n"
227
- Debugger.breakpoints.each_with_index do |b, n|
228
- if b.expr.nil?
229
- stdout.printf " %d %s:%s\n", n+1, b.source, b.pos
230
- else
231
- stdout.printf " %d %s:%s if %s\n", n+1, b.source, b.pos, b.expr
232
- end
233
- end
234
- stdout.puts
235
- else
236
- stdout.print "No breakpoints\n"
237
- end
238
- when /^\s*del(?:ete)?(?:\s+(\d+))?$/
239
- pos = $1
240
- unless pos
241
- input = readline("Clear all breakpoints? (y/n) ", false)
242
- if input == "y"
243
- Debugger.breakpoints.clear
244
- end
245
- else
246
- pos = pos.to_i
247
- unless Debugger.breakpoints.delete_at(pos-1)
248
- stdout.printf "Breakpoint %d is not defined\n", pos
249
- end
250
- end
251
-
252
- when /^\s*th(?:read)?\s+/
253
- if Debugger.debug_thread_info($') == :cont
254
- prompt = false
255
- end
256
-
257
- when /^\s*m(?:ethod)?\s+/
258
- debug_method_info($', binding)
259
-
260
- when /^\s*pp\s+/
261
- PP.pp(debug_eval($', binding), stdout) rescue stdout.puts $!.message
262
-
263
- when /^\s*p\s+/
264
- stdout.printf "%s\n", debug_eval($', binding).inspect
265
-
266
- when /^\s*h(?:elp)?$/
267
- debug_print_help()
268
-
269
- when /^\s*q(?:uit)?$/
270
- input = readline("Really quit? (y/n) ", false)
271
- if input == "y"
272
- exit! # exit -> exit!: No graceful way to stop threads...
273
- end
274
-
275
- when /^\s*disp(?:lay)?\s+(.+)$/
276
- exp = $1
277
- display.push [true, exp]
278
- stdout.printf "%d: ", display.size
279
- display_expression(exp, binding)
280
-
281
- when /^\s*disp(?:lay)?$/
282
- display_expressions(binding)
283
-
284
- when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
285
- pos = $1
286
- unless pos
287
- input = readline("Clear all expressions? (y/n) ", false)
288
- if input == "y"
289
- for d in display
290
- d[0] = false
291
- end
292
- end
293
- else
294
- pos = pos.to_i
295
- if display[pos-1]
296
- display[pos-1][0] = false
297
- else
298
- stdout.printf "Display expression %d is not defined\n", pos
299
- end
300
- end
301
-
302
- when /^\s*cat(?:ch)?(?:\s+(.+))?$/
303
- if $1
304
- excn = $1
305
- if excn == 'off'
306
- Debugger.catchpoint = nil
307
- stdout.print "Clear catchpoint.\n"
308
- else
309
- Debugger.catchpoint = excn
310
- stdout.printf "Set catchpoint %s.\n", excn
311
- end
312
- else
313
- if Debugger.catchpoint
314
- stdout.printf "Catchpoint %s.\n", Debugger.catchpoint
315
- else
316
- stdout.print "No catchpoint.\n"
317
- end
318
- end
319
-
320
- when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
321
- if defined?( $2 )
322
- Debugger.tracing = $1 == 'on'
323
- elsif defined?( $1 )
324
- self.tracing = $1 == 'on'
325
- end
326
- if Debugger.tracing || self.tracing
327
- stdout.print "Trace on.\n"
328
- else
329
- stdout.print "Trace off.\n"
330
- end
331
-
332
- else
333
- v = debug_eval(input, binding)
334
- stdout.printf "%s\n", v.inspect
335
- end
336
- end
337
- end
75
+ processor.at_line(self, file, line, binding)
338
76
  MUTEX.unlock
339
77
  Debugger.resume
340
78
  end
341
-
342
- def debug_print_help
343
- stdout.print <<EOHELP
344
- ruby-debug help v.#{Debugger::VERSION}
345
- Commands
346
- b[reak] [file|class:]<line|method> [if expr]
347
- b[reak] [class.]<line|method> [if expr]
348
- set breakpoint to some position,
349
- optionally if expr == true
350
- cat[ch] <an Exception> set catchpoint to an exception
351
- cat[ch] show catchpoint
352
- disp[lay] <expression> add expression into display expression list
353
- undisp[lay][ nnn] delete one particular or all display expressions
354
- b[reak] list breakpoints
355
- del[ete][ nnn] delete some or all breakpoints
356
- c[ont] run until program ends or hit breakpoint
357
- r[un] alias for cont
358
- s[tep][ nnn] step (into methods) one line or till line nnn
359
- n[ext][ nnn] go over one line or till line nnn
360
- w[here] display frames
361
- f[rame] alias for where
362
- l[ist][ (-|nn-mm)] list program, - list backwards, nn-mm list given lines
363
- up[ nn] move to higher frame
364
- down[ nn] move to lower frame
365
- fin[ish] return to outer frame
366
- q[uit] exit from debugger
367
- v[ar] g[lobal] show global variables
368
- v[ar] l[ocal] show local variables
369
- v[ar] i[nstance] <object> show instance variables of object
370
- v[ar] c[onst] <object> show constants of object
371
- m[ethod] i[nstance] <obj> show methods of object
372
- m[ethod] <class|module> show instance methods of class or module
373
- th[read] l[ist] list all threads
374
- th[read] c[ur[rent]] show current thread
375
- th[read] [sw[itch]] <nnn> switch thread context to nnn
376
- th[read] stop <nnn> stop thread nnn
377
- th[read] resume <nnn> resume thread nnn
378
- p expression evaluate expression and print its value
379
- pp expression evaluate expression and print its value
380
- h[elp] print this help
381
- <everything else> evaluate
382
- EOHELP
383
- end
384
-
385
- def display_expressions(binding)
386
- n = 1
387
- for d in display
388
- if d[0]
389
- stdout.printf "%d: ", n
390
- display_expression(d[1], binding)
391
- end
392
- n += 1
393
- end
394
- end
395
-
396
- def display_expression(exp, binding)
397
- stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
398
- end
399
-
400
- def debug_eval(str, binding)
401
- begin
402
- val = eval(str, binding)
403
- rescue StandardError, ScriptError => e
404
- at = eval("caller(1)", binding)
405
- stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
406
- for i in at
407
- stdout.printf "\tfrom %s\n", i
408
- end
409
- throw :debug_error
410
- end
411
- end
412
-
413
- def debug_silent_eval(str, binding)
414
- begin
415
- eval(str, binding)
416
- rescue StandardError, ScriptError
417
- nil
418
- end
419
- end
420
-
421
- def debug_variable_info(input, binding)
422
- case input
423
- when /^\s*g(?:lobal)?\s*$/
424
- var_list(global_variables, binding)
425
-
426
- when /^\s*l(?:ocal)?\s*$/
427
- var_list(eval("local_variables", binding), binding)
428
-
429
- when /^\s*i(?:nstance)?\s+/
430
- obj = debug_eval($', binding)
431
- var_list(obj.instance_variables, obj.instance_eval{binding()})
432
-
433
- when /^\s*c(?:onst(?:ant)?)?\s+/
434
- obj = debug_eval($', binding)
435
- unless obj.kind_of? Module
436
- stdout.print "Should be Class/Module: ", $', "\n"
437
- else
438
- var_list(obj.constants, obj.module_eval{binding()})
439
- end
440
- end
441
- end
442
-
443
- def display_frames(pos)
444
- self.frames.each_with_index do |frame, idx|
445
- if idx == pos
446
- stdout.print "--> "
447
- else
448
- stdout.print " "
449
- end
450
- stdout.print format_frame(frame, idx)
451
- end
452
- end
453
-
454
- def format_frame(frame, pos)
455
- bind, file, line, id = frame.binding, frame.file, frame.line, frame.id
456
- sprintf "#%d %s:%s%s\n", pos + 1, file, line,
457
- (id ? ":in `#{id.id2name}'" : "")
458
- end
459
-
460
- def var_list(ary, binding)
461
- ary.sort!
462
- for v in ary
463
- stdout.printf " %s => %s\n", v, eval(v, binding).inspect
464
- end
465
- end
466
-
467
- def display_list(b, e, file, line)
468
- stdout.printf "[%d, %d] in %s\n", b, e, file
469
- if lines = SCRIPT_LINES__[file] and lines != true
470
- n = 0
471
- b.upto(e) do |n|
472
- if n > 0 && lines[n-1]
473
- if n == line
474
- stdout.printf "=> %d %s\n", n, lines[n-1].chomp
475
- else
476
- stdout.printf " %d %s\n", n, lines[n-1].chomp
477
- end
478
- end
479
- end
480
- else
481
- stdout.printf "No sourcefile available for %s\n", file
482
- end
483
- end
484
-
485
- def line_at(file, line)
486
- lines = SCRIPT_LINES__[file]
487
- if lines
488
- return "\n" if lines == true
489
- line = lines[line-1]
490
- return "\n" unless line
491
- return line.gsub(/^\s+/, '')
492
- end
493
- return "\n"
494
- end
495
-
496
- def display
497
- Debugger.display
498
- end
499
79
  end
500
80
 
501
81
  class << self
502
- def stdout
503
- @stdout
504
- end
505
-
506
- def stdout=(v)
507
- @stdout = v
508
- end
509
-
510
- def set_trace_proc &block
511
- @trace_proc = block
512
- end
513
-
514
- def trace_proc
515
- @trace_proc
516
- end
517
-
518
- def display
519
- @display
520
- end
521
-
522
- def debug_method_info(input, binding)
523
- case input
524
- when /^i(:?nstance)?\s+/
525
- obj = debug_eval($', binding)
526
-
527
- len = 0
528
- for v in obj.methods.sort
529
- len += v.size + 1
530
- if len > 70
531
- len = v.size + 1
532
- stdout.print "\n"
533
- end
534
- stdout.print v, " "
535
- end
536
- stdout.print "\n"
537
-
538
- else
539
- obj = debug_eval(input, binding)
540
- unless obj.kind_of? Module
541
- stdout.print "Should be Class/Module: ", input, "\n"
542
- else
543
- len = 0
544
- for v in obj.instance_methods(false).sort
545
- len += v.size + 1
546
- if len > 70
547
- len = v.size + 1
548
- stdout.print "\n"
549
- end
550
- stdout.print v, " "
551
- end
552
- stdout.print "\n"
553
- end
554
- end
555
- end
556
-
557
- def display_context(c)
558
- if c.thread == Thread.current
559
- stdout.print "+"
560
- else
561
- stdout.print " "
562
- end
563
- stdout.printf "%d ", c.thnum
564
- stdout.print c.thread.inspect, "\t"
565
- last_frame = c.frames.first
566
- if last_frame
567
- @stdout.print last_frame.file,":",last_frame.line
568
- end
569
- @stdout.print "\n"
570
- end
571
-
572
- def display_all_contexts
573
- threads = contexts.sort_by{|c| c.thnum}.each do |c|
574
- display_context(c)
575
- end
576
- end
577
-
578
- def get_context(thnum)
579
- contexts.find{|c| c.thnum = thnum}
580
- end
581
-
582
- def debug_thread_info(input)
583
- case input
584
- when /^l(?:ist)?/
585
- display_all_contexts
586
-
587
- when /^c(?:ur(?:rent)?)?$/
588
- display_context(current_context)
589
-
590
- when /^(?:sw(?:itch)?\s+)?(\d+)/
591
- c = get_context($1.to_i)
592
- if c == current_context
593
- stdout.print "It's the current thread.\n"
594
- else
595
- display_context(c)
596
- c.stop_next = 1
597
- c.thread.run
598
- return :cont
599
- end
600
-
601
- when /^stop\s+(\d+)/
602
- c = get_context($1.to_i)
603
- if c == current_context
604
- stdout.print "It's the current thread.\n"
605
- elsif c.thread.stop?
606
- stdout.print "Already stopped.\n"
607
- else
608
- display_context(c)
609
- c.set_suspend
610
- end
611
-
612
- when /^resume\s+(\d+)/
613
- c = get_context($1.to_i)
614
- if c == current_context
615
- stdout.print "It's the current thread.\n"
616
- elsif !c.thread.stop?
617
- stdout.print "Already running."
618
- else
619
- display_context(c)
620
- c.thread.run
82
+ attr_accessor :processor
83
+ attr_reader :thread
84
+
85
+ def interface=(value)
86
+ processor.interface = value
87
+ end
88
+
89
+ def start_server(host = nil, port = PORT)
90
+ return if @thread
91
+ require "socket"
92
+
93
+ server = TCPServer.new(host, port)
94
+ @thread = Thread.start do
95
+ while (session = server.accept)
96
+ interface = RemoteInterface.new(session)
97
+ self.interface = interface
621
98
  end
622
99
  end
623
100
  end
@@ -628,6 +105,4 @@ module Kernel
628
105
  def debugger(steps = 1)
629
106
  Debugger.current_context.stop_next = steps
630
107
  end
631
- end
632
-
633
- Debugger.start
108
+ end