ruby-debug 0.1.5 → 0.2

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/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
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: ruby-debug
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.5
7
- date: 2006-07-13 08:20:06 -04:00
6
+ version: "0.2"
7
+ date: 2006-07-17 02:11:17 -04:00
8
8
  summary: Fast Ruby debugger
9
9
  require_paths:
10
10
  - lib
@@ -33,10 +33,15 @@ files:
33
33
  - README
34
34
  - LICENSE
35
35
  - CHANGES
36
+ - lib/ruby-debug
36
37
  - lib/ruby-debug.rb
38
+ - lib/ruby-debug/interface.rb
39
+ - lib/ruby-debug/processor.rb
37
40
  - ext/extconf.rb
38
41
  - ext/ruby_debug.c
42
+ - ext/win32
39
43
  - bin/rdebug
44
+ - bin/remote
40
45
  test_files: []
41
46
 
42
47
  rdoc_options: []