ruby-debug 0.1.5-mswin32 → 0.2-mswin32

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.
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