rfs 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/MIT-LICENSE +7 -0
  2. data/Rakefile.rb +193 -0
  3. data/bin/RenameFileSet.rbw +14 -0
  4. data/bin/rfs.rb +214 -0
  5. data/bin/rfsd.rb +8 -0
  6. data/description.txt +24 -0
  7. data/lib/RenameFileSet.bak.rb +372 -0
  8. data/lib/errors.rb +15 -0
  9. data/lib/filters.rb +68 -0
  10. data/lib/gui.rb +216 -0
  11. data/lib/innate/array.rb +104 -0
  12. data/lib/innate/coverage.rb +315 -0
  13. data/lib/innate/debug.rb +12 -0
  14. data/lib/innate/debugger.rb +944 -0
  15. data/lib/innate/file.rb +5 -0
  16. data/lib/innate/filelines.rb +148 -0
  17. data/lib/innate/kernel.rb +41 -0
  18. data/lib/innate/metaid.rb +30 -0
  19. data/lib/innate/mkdirs.rb +12 -0
  20. data/lib/innate/regexp.rb +80 -0
  21. data/lib/innate/reload.rb +11 -0
  22. data/lib/innate/roman.rb +72 -0
  23. data/lib/innate/scriptlines.rb +60 -0
  24. data/lib/innate/string.rb +56 -0
  25. data/lib/innate/test/all_tests.rb +11 -0
  26. data/lib/innate/test/files/mkdirs_dummy.file +1 -0
  27. data/lib/innate/test/files/reloadtarget.rb +5 -0
  28. data/lib/innate/test/files/reloadtarget1.rb +5 -0
  29. data/lib/innate/test/files/reloadtarget2.rb +5 -0
  30. data/lib/innate/test/test_coverage.rb +13 -0
  31. data/lib/innate/test/testarray.rb +98 -0
  32. data/lib/innate/test/testfile.rb +15 -0
  33. data/lib/innate/test/testfilelines.rb +106 -0
  34. data/lib/innate/test/testkernel.rb +30 -0
  35. data/lib/innate/test/testmkdirs.rb +19 -0
  36. data/lib/innate/test/testregexp.rb +86 -0
  37. data/lib/innate/test/testreload.rb +61 -0
  38. data/lib/innate/test/testroman.rb +54 -0
  39. data/lib/innate/test/testscriptlines.rb +39 -0
  40. data/lib/innate/test/teststring.rb +52 -0
  41. data/lib/innate/test/testtitlecase.rb +20 -0
  42. data/lib/innate/titlecase.rb +64 -0
  43. data/lib/innate/tracerequire.rb +22 -0
  44. data/lib/namesource.rb +53 -0
  45. data/lib/options.rb +64 -0
  46. data/lib/providers.rb +93 -0
  47. data/lib/regexp.rb +56 -0
  48. data/lib/rename_functions.rb +142 -0
  49. data/lib/renamer.rb +210 -0
  50. data/lib/results.rb +83 -0
  51. data/lib/test/test_helper.rb +147 -0
  52. data/tests/dir/file1 +0 -0
  53. data/tests/dir/file2 +0 -0
  54. data/tests/dir/file3 +0 -0
  55. data/tests/test_helper.rb +147 -0
  56. data/tests/test_rename_functions.rb +605 -0
  57. metadata +105 -0
@@ -0,0 +1,12 @@
1
+ require 'innate/scriptlines'
2
+
3
+ def debug
4
+ if $SAFE == 0
5
+ if require('innate/debugger')
6
+ DEBUGGER__.start_debugger
7
+ else
8
+ DEBUGGER__.interrupt
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,944 @@
1
+ # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
2
+ # Copyright (C) 2000 Information-technology Promotion Agency, Japan
3
+ # Copyright (C) 2000-2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
4
+
5
+ if $SAFE > 0
6
+ STDERR.print "-r debug.rb is not available in safe mode\n"
7
+ exit 1
8
+ end
9
+
10
+ require 'tracer'
11
+ require 'pp'
12
+
13
+ class Tracer
14
+ def Tracer.trace_func(*vars)
15
+ Single.trace_func(*vars)
16
+ end
17
+ end
18
+
19
+ SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
20
+
21
+ class DEBUGGER__
22
+ class Mutex
23
+ def initialize
24
+ @locker = nil
25
+ @waiting = []
26
+ @locked = false;
27
+ end
28
+
29
+ def locked?
30
+ @locked
31
+ end
32
+
33
+ def lock
34
+ return if Thread.critical
35
+ return if @locker == Thread.current
36
+ while (Thread.critical = true; @locked)
37
+ @waiting.push Thread.current
38
+ Thread.stop
39
+ end
40
+ @locked = true
41
+ @locker = Thread.current
42
+ Thread.critical = false
43
+ self
44
+ end
45
+
46
+ def unlock
47
+ return if Thread.critical
48
+ return unless @locked
49
+ unless @locker == Thread.current
50
+ raise RuntimeError, "unlocked by other"
51
+ end
52
+ Thread.critical = true
53
+ t = @waiting.shift
54
+ @locked = false
55
+ @locker = nil
56
+ Thread.critical = false
57
+ t.run if t
58
+ self
59
+ end
60
+ end
61
+ MUTEX = Mutex.new
62
+
63
+ class Context
64
+ DEBUG_LAST_CMD = []
65
+
66
+ begin
67
+ require 'readline'
68
+ def readline(prompt, hist)
69
+ Readline::readline(prompt, hist)
70
+ end
71
+ rescue LoadError
72
+ def readline(prompt, hist)
73
+ STDOUT.print prompt
74
+ STDOUT.flush
75
+ line = STDIN.gets
76
+ exit unless line
77
+ line.chomp!
78
+ line
79
+ end
80
+ USE_READLINE = false
81
+ end
82
+
83
+ def initialize
84
+ if Thread.current == Thread.main
85
+ @stop_next = 1
86
+ else
87
+ @stop_next = 0
88
+ end
89
+ @last_file = nil
90
+ @file = nil
91
+ @line = nil
92
+ @no_step = nil
93
+ @frames = []
94
+ @finish_pos = 0
95
+ @trace = false
96
+ @catch = "StandardError"
97
+ @suspend_next = false
98
+ end
99
+
100
+ def stop_next(n=1)
101
+ @stop_next = n
102
+ end
103
+
104
+ def set_suspend
105
+ @suspend_next = true
106
+ end
107
+
108
+ def clear_suspend
109
+ @suspend_next = false
110
+ end
111
+
112
+ def suspend_all
113
+ DEBUGGER__.suspend
114
+ end
115
+
116
+ def resume_all
117
+ DEBUGGER__.resume
118
+ end
119
+
120
+ def check_suspend
121
+ return if Thread.critical
122
+ while (Thread.critical = true; @suspend_next)
123
+ DEBUGGER__.waiting.push Thread.current
124
+ @suspend_next = false
125
+ Thread.stop
126
+ end
127
+ Thread.critical = false
128
+ end
129
+
130
+ def trace?
131
+ @trace
132
+ end
133
+
134
+ def set_trace(arg)
135
+ @trace = arg
136
+ end
137
+
138
+ def stdout
139
+ DEBUGGER__.stdout
140
+ end
141
+
142
+ def break_points
143
+ DEBUGGER__.break_points
144
+ end
145
+
146
+ def display
147
+ DEBUGGER__.display
148
+ end
149
+
150
+ def context(th)
151
+ DEBUGGER__.context(th)
152
+ end
153
+
154
+ def set_trace_all(arg)
155
+ DEBUGGER__.set_trace(arg)
156
+ end
157
+
158
+ def set_last_thread(th)
159
+ DEBUGGER__.set_last_thread(th)
160
+ end
161
+
162
+ def debug_eval(str, binding)
163
+ begin
164
+ val = eval(str, binding)
165
+ rescue StandardError, ScriptError => e
166
+ at = eval("caller(1)", binding)
167
+ stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
168
+ for i in at
169
+ stdout.printf "\tfrom %s\n", i
170
+ end
171
+ throw :debug_error
172
+ end
173
+ end
174
+
175
+ def debug_silent_eval(str, binding)
176
+ begin
177
+ eval(str, binding)
178
+ rescue StandardError, ScriptError
179
+ nil
180
+ end
181
+ end
182
+
183
+ def var_list(ary, binding)
184
+ ary.sort!
185
+ for v in ary
186
+ stdout.printf " %s => %s\n", v, eval(v, binding).inspect
187
+ end
188
+ end
189
+
190
+ def debug_variable_info(input, binding)
191
+ case input
192
+ when /^\s*g(?:lobal)?\s*$/
193
+ var_list(global_variables, binding)
194
+
195
+ when /^\s*l(?:ocal)?\s*$/
196
+ var_list(eval("local_variables", binding), binding)
197
+
198
+ when /^\s*i(?:nstance)?\s+/
199
+ obj = debug_eval($', binding)
200
+ var_list(obj.instance_variables, obj.instance_eval{binding()})
201
+
202
+ when /^\s*c(?:onst(?:ant)?)?\s+/
203
+ obj = debug_eval($', binding)
204
+ unless obj.kind_of? Module
205
+ stdout.print "Should be Class/Module: ", $', "\n"
206
+ else
207
+ var_list(obj.constants, obj.module_eval{binding()})
208
+ end
209
+ end
210
+ end
211
+
212
+ def debug_method_info(input, binding)
213
+ case input
214
+ when /^i(:?nstance)?\s+/
215
+ obj = debug_eval($', binding)
216
+
217
+ len = 0
218
+ for v in obj.methods.sort
219
+ len += v.size + 1
220
+ if len > 70
221
+ len = v.size + 1
222
+ stdout.print "\n"
223
+ end
224
+ stdout.print v, " "
225
+ end
226
+ stdout.print "\n"
227
+
228
+ else
229
+ obj = debug_eval(input, binding)
230
+ unless obj.kind_of? Module
231
+ stdout.print "Should be Class/Module: ", input, "\n"
232
+ else
233
+ len = 0
234
+ for v in obj.instance_methods(false).sort
235
+ len += v.size + 1
236
+ if len > 70
237
+ len = v.size + 1
238
+ stdout.print "\n"
239
+ end
240
+ stdout.print v, " "
241
+ end
242
+ stdout.print "\n"
243
+ end
244
+ end
245
+ end
246
+
247
+ def thnum
248
+ num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
249
+ unless num
250
+ DEBUGGER__.make_thread_list
251
+ num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
252
+ end
253
+ num
254
+ end
255
+
256
+ def debug_command(file, line, id, binding)
257
+ MUTEX.lock
258
+ set_last_thread(Thread.current)
259
+ frame_pos = 0
260
+ binding_file = file
261
+ binding_line = line
262
+ previous_line = nil
263
+ if ENV['EMACS']
264
+ stdout.printf "\032\032%s:%d:\n", binding_file, binding_line
265
+ else
266
+ stdout.printf "%s:%d:%s", binding_file, binding_line,
267
+ line_at(binding_file, binding_line)
268
+ end
269
+ @frames[0] = [binding, file, line, id]
270
+ display_expressions(binding)
271
+ prompt = true
272
+ while prompt and input = readline("(rdb:%d) "%thnum(), true)
273
+ catch(:debug_error) do
274
+ if input == ""
275
+ next unless DEBUG_LAST_CMD[0]
276
+ input = DEBUG_LAST_CMD[0]
277
+ stdout.print input, "\n"
278
+ else
279
+ DEBUG_LAST_CMD[0] = input
280
+ end
281
+
282
+ case input
283
+ when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
284
+ if defined?( $2 )
285
+ if $1 == 'on'
286
+ set_trace_all true
287
+ else
288
+ set_trace_all false
289
+ end
290
+ elsif defined?( $1 )
291
+ if $1 == 'on'
292
+ set_trace true
293
+ else
294
+ set_trace false
295
+ end
296
+ end
297
+ if trace?
298
+ stdout.print "Trace on.\n"
299
+ else
300
+ stdout.print "Trace off.\n"
301
+ end
302
+
303
+ when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/
304
+ pos = $2
305
+ if $1
306
+ klass = debug_silent_eval($1, binding)
307
+ file = $1
308
+ end
309
+ if pos =~ /^\d+$/
310
+ pname = pos
311
+ pos = pos.to_i
312
+ else
313
+ pname = pos = pos.intern.id2name
314
+ end
315
+ break_points.push [true, 0, klass || file, pos]
316
+ stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname
317
+
318
+ when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/
319
+ pos = $2.intern.id2name
320
+ klass = debug_eval($1, binding)
321
+ break_points.push [true, 0, klass, pos]
322
+ stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos
323
+
324
+ when /^\s*wat(?:ch)?\s+(.+)$/
325
+ exp = $1
326
+ break_points.push [true, 1, exp]
327
+ stdout.printf "Set watchpoint %d\n", break_points.size, exp
328
+
329
+ when /^\s*b(?:reak)?$/
330
+ if break_points.find{|b| b[1] == 0}
331
+ n = 1
332
+ stdout.print "Breakpoints:\n"
333
+ for b in break_points
334
+ if b[0] and b[1] == 0
335
+ stdout.printf " %d %s:%s\n", n, b[2], b[3]
336
+ end
337
+ n += 1
338
+ end
339
+ end
340
+ if break_points.find{|b| b[1] == 1}
341
+ n = 1
342
+ stdout.print "\n"
343
+ stdout.print "Watchpoints:\n"
344
+ for b in break_points
345
+ if b[0] and b[1] == 1
346
+ stdout.printf " %d %s\n", n, b[2]
347
+ end
348
+ n += 1
349
+ end
350
+ end
351
+ if break_points.size == 0
352
+ stdout.print "No breakpoints\n"
353
+ else
354
+ stdout.print "\n"
355
+ end
356
+
357
+ when /^\s*del(?:ete)?(?:\s+(\d+))?$/
358
+ pos = $1
359
+ unless pos
360
+ input = readline("Clear all breakpoints? (y/n) ", false)
361
+ if input == "y"
362
+ for b in break_points
363
+ b[0] = false
364
+ end
365
+ end
366
+ else
367
+ pos = pos.to_i
368
+ if break_points[pos-1]
369
+ break_points[pos-1][0] = false
370
+ else
371
+ stdout.printf "Breakpoint %d is not defined\n", pos
372
+ end
373
+ end
374
+
375
+ when /^\s*disp(?:lay)?\s+(.+)$/
376
+ exp = $1
377
+ display.push [true, exp]
378
+ stdout.printf "%d: ", display.size
379
+ display_expression(exp, binding)
380
+
381
+ when /^\s*disp(?:lay)?$/
382
+ display_expressions(binding)
383
+
384
+ when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
385
+ pos = $1
386
+ unless pos
387
+ input = readline("Clear all expressions? (y/n) ", false)
388
+ if input == "y"
389
+ for d in display
390
+ d[0] = false
391
+ end
392
+ end
393
+ else
394
+ pos = pos.to_i
395
+ if display[pos-1]
396
+ display[pos-1][0] = false
397
+ else
398
+ stdout.printf "Display expression %d is not defined\n", pos
399
+ end
400
+ end
401
+
402
+ when /^\s*c(?:ont)?$/
403
+ prompt = false
404
+
405
+ when /^\s*s(?:tep)?(?:\s+(\d+))?$/
406
+ if $1
407
+ lev = $1.to_i
408
+ else
409
+ lev = 1
410
+ end
411
+ @stop_next = lev
412
+ prompt = false
413
+
414
+ when /^\s*n(?:ext)?(?:\s+(\d+))?$/
415
+ if $1
416
+ lev = $1.to_i
417
+ else
418
+ lev = 1
419
+ end
420
+ @stop_next = lev
421
+ @no_step = @frames.size - frame_pos
422
+ prompt = false
423
+
424
+ when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
425
+ display_frames(frame_pos)
426
+
427
+ when /^\s*l(?:ist)?(?:\s+(.+))?$/
428
+ if not $1
429
+ b = previous_line ? previous_line + 10 : binding_line - 5
430
+ e = b + 9
431
+ elsif $1 == '-'
432
+ b = previous_line ? previous_line - 10 : binding_line - 5
433
+ e = b + 9
434
+ else
435
+ b, e = $1.split(/[-,]/)
436
+ if e
437
+ b = b.to_i
438
+ e = e.to_i
439
+ else
440
+ b = b.to_i - 5
441
+ e = b + 9
442
+ end
443
+ end
444
+ previous_line = b
445
+ display_list(b, e, binding_file, binding_line)
446
+
447
+ when /^\s*up(?:\s+(\d+))?$/
448
+ previous_line = nil
449
+ if $1
450
+ lev = $1.to_i
451
+ else
452
+ lev = 1
453
+ end
454
+ frame_pos += lev
455
+ if frame_pos >= @frames.size
456
+ frame_pos = @frames.size - 1
457
+ stdout.print "At toplevel\n"
458
+ end
459
+ binding, binding_file, binding_line = @frames[frame_pos]
460
+ stdout.print format_frame(frame_pos)
461
+
462
+ when /^\s*down(?:\s+(\d+))?$/
463
+ previous_line = nil
464
+ if $1
465
+ lev = $1.to_i
466
+ else
467
+ lev = 1
468
+ end
469
+ frame_pos -= lev
470
+ if frame_pos < 0
471
+ frame_pos = 0
472
+ stdout.print "At stack bottom\n"
473
+ end
474
+ binding, binding_file, binding_line = @frames[frame_pos]
475
+ stdout.print format_frame(frame_pos)
476
+
477
+ when /^\s*fin(?:ish)?$/
478
+ if frame_pos == @frames.size
479
+ stdout.print "\"finish\" not meaningful in the outermost frame.\n"
480
+ else
481
+ @finish_pos = @frames.size - frame_pos
482
+ frame_pos = 0
483
+ prompt = false
484
+ end
485
+
486
+ when /^\s*cat(?:ch)?(?:\s+(.+))?$/
487
+ if $1
488
+ excn = $1
489
+ if excn == 'off'
490
+ @catch = nil
491
+ stdout.print "Clear catchpoint.\n"
492
+ else
493
+ @catch = excn
494
+ stdout.printf "Set catchpoint %s.\n", @catch
495
+ end
496
+ else
497
+ if @catch
498
+ stdout.printf "Catchpoint %s.\n", @catch
499
+ else
500
+ stdout.print "No catchpoint.\n"
501
+ end
502
+ end
503
+
504
+ when /^\s*q(?:uit)?$/
505
+ input = readline("Really quit? (y/n) ", false)
506
+ if input == "y"
507
+ exit! # exit -> exit!: No graceful way to stop threads...
508
+ end
509
+
510
+ when /^\s*v(?:ar)?\s+/
511
+ debug_variable_info($', binding)
512
+
513
+ when /^\s*m(?:ethod)?\s+/
514
+ debug_method_info($', binding)
515
+
516
+ when /^\s*th(?:read)?\s+/
517
+ if DEBUGGER__.debug_thread_info($', binding) == :cont
518
+ prompt = false
519
+ end
520
+
521
+ when /^\s*pp\s+/
522
+ PP.pp(debug_eval($', binding), stdout)
523
+
524
+ when /^\s*p\s+/
525
+ stdout.printf "%s\n", debug_eval($', binding).inspect
526
+
527
+ when /^\s*h(?:elp)?$/
528
+ debug_print_help()
529
+
530
+ else
531
+ v = debug_eval(input, binding)
532
+ stdout.printf "%s\n", v.inspect
533
+ end
534
+ end
535
+ end
536
+ MUTEX.unlock
537
+ resume_all
538
+ end
539
+
540
+ def debug_print_help
541
+ stdout.print <<EOHELP
542
+ Debugger help v.-0.002b
543
+ Commands
544
+ b[reak] [file|class:]<line|method>
545
+ b[reak] [class.]<line|method>
546
+ set breakpoint to some position
547
+ wat[ch] <expression> set watchpoint to some expression
548
+ cat[ch] <an Exception> set catchpoint to an exception
549
+ b[reak] list breakpoints
550
+ cat[ch] show catchpoint
551
+ del[ete][ nnn] delete some or all breakpoints
552
+ disp[lay] <expression> add expression into display expression list
553
+ undisp[lay][ nnn] delete one particular or all display expressions
554
+ c[ont] run until program ends or hit breakpoint
555
+ s[tep][ nnn] step (into methods) one line or till line nnn
556
+ n[ext][ nnn] go over one line or till line nnn
557
+ w[here] display frames
558
+ f[rame] alias for where
559
+ l[ist][ (-|nn-mm)] list program, - lists backwards
560
+ nn-mm lists given lines
561
+ up[ nn] move to higher frame
562
+ down[ nn] move to lower frame
563
+ fin[ish] return to outer frame
564
+ tr[ace] (on|off) set trace mode of current thread
565
+ tr[ace] (on|off) all set trace mode of all threads
566
+ q[uit] exit from debugger
567
+ v[ar] g[lobal] show global variables
568
+ v[ar] l[ocal] show local variables
569
+ v[ar] i[nstance] <object> show instance variables of object
570
+ v[ar] c[onst] <object> show constants of object
571
+ m[ethod] i[nstance] <obj> show methods of object
572
+ m[ethod] <class|module> show instance methods of class or module
573
+ th[read] l[ist] list all threads
574
+ th[read] c[ur[rent]] show current thread
575
+ th[read] [sw[itch]] <nnn> switch thread context to nnn
576
+ th[read] stop <nnn> stop thread nnn
577
+ th[read] resume <nnn> resume thread nnn
578
+ p expression evaluate expression and print its value
579
+ h[elp] print this help
580
+ <everything else> evaluate
581
+ EOHELP
582
+ end
583
+
584
+ def display_expressions(binding)
585
+ n = 1
586
+ for d in display
587
+ if d[0]
588
+ stdout.printf "%d: ", n
589
+ display_expression(d[1], binding)
590
+ end
591
+ n += 1
592
+ end
593
+ end
594
+
595
+ def display_expression(exp, binding)
596
+ stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
597
+ end
598
+
599
+ def frame_set_pos(file, line)
600
+ if @frames[0]
601
+ @frames[0][1] = file
602
+ @frames[0][2] = line
603
+ end
604
+ end
605
+
606
+ def display_frames(pos)
607
+ 0.upto(@frames.size - 1) do |n|
608
+ if n == pos
609
+ stdout.print "--> "
610
+ else
611
+ stdout.print " "
612
+ end
613
+ stdout.print format_frame(n)
614
+ end
615
+ end
616
+
617
+ def format_frame(pos)
618
+ bind, file, line, id = @frames[pos]
619
+ sprintf "#%d %s:%s%s\n", pos + 1, file, line,
620
+ (id ? ":in `#{id.id2name}'" : "")
621
+ end
622
+
623
+ def display_list(b, e, file, line)
624
+ stdout.printf "[%d, %d] in %s\n", b, e, file
625
+ if lines = SCRIPT_LINES__[file] and lines != true
626
+ n = 0
627
+ b.upto(e) do |n|
628
+ if n > 0 && lines[n-1]
629
+ if n == line
630
+ stdout.printf "=> %d %s\n", n, lines[n-1].chomp
631
+ else
632
+ stdout.printf " %d %s\n", n, lines[n-1].chomp
633
+ end
634
+ end
635
+ end
636
+ else
637
+ stdout.printf "No sourcefile available for %s\n", file
638
+ end
639
+ end
640
+
641
+ def line_at(file, line)
642
+ lines = SCRIPT_LINES__[file]
643
+ if lines
644
+ return "\n" if lines == true
645
+ line = lines[line-1]
646
+ return "\n" unless line
647
+ return line
648
+ end
649
+ return "\n"
650
+ end
651
+
652
+ def debug_funcname(id)
653
+ if id.nil?
654
+ "toplevel"
655
+ else
656
+ id.id2name
657
+ end
658
+ end
659
+
660
+ def check_break_points(file, klass, pos, binding, id)
661
+ return false if break_points.empty?
662
+ n = 1
663
+ for b in break_points
664
+ if b[0] # valid
665
+ if b[1] == 0 # breakpoint
666
+ if (b[2] == file and b[3] == pos) or
667
+ (klass and b[2] == klass and b[3] == pos)
668
+ stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
669
+ return true
670
+ end
671
+ elsif b[1] == 1 # watchpoint
672
+ if debug_silent_eval(b[2], binding)
673
+ stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
674
+ return true
675
+ end
676
+ end
677
+ end
678
+ n += 1
679
+ end
680
+ return false
681
+ end
682
+
683
+ def excn_handle(file, line, id, binding)
684
+ if $!.class <= SystemExit
685
+ set_trace_func nil
686
+ exit
687
+ end
688
+
689
+ if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch })
690
+ stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class
691
+ fs = @frames.size
692
+ tb = caller(0)[-fs..-1]
693
+ if tb
694
+ for i in tb
695
+ stdout.printf "\tfrom %s\n", i
696
+ end
697
+ end
698
+ suspend_all
699
+ debug_command(file, line, id, binding)
700
+ end
701
+ end
702
+
703
+ def trace_func(event, file, line, id, binding, klass)
704
+ Tracer.trace_func(event, file, line, id, binding, klass) if trace?
705
+ context(Thread.current).check_suspend
706
+ @file = file
707
+ @line = line
708
+ case event
709
+ when 'line'
710
+ frame_set_pos(file, line)
711
+ if !@no_step or @frames.size == @no_step
712
+ @stop_next -= 1
713
+ @stop_next = -1 if @stop_next < 0
714
+ elsif @frames.size < @no_step
715
+ @stop_next = 0 # break here before leaving...
716
+ else
717
+ # nothing to do. skipped.
718
+ end
719
+ if @stop_next == 0 or check_break_points(file, nil, line, binding, id)
720
+ @no_step = nil
721
+ suspend_all
722
+ debug_command(file, line, id, binding)
723
+ end
724
+
725
+ when 'call'
726
+ @frames.unshift [binding, file, line, id]
727
+ if check_break_points(file, klass, id.id2name, binding, id)
728
+ suspend_all
729
+ debug_command(file, line, id, binding)
730
+ end
731
+
732
+ when 'c-call'
733
+ frame_set_pos(file, line)
734
+
735
+ when 'class'
736
+ @frames.unshift [binding, file, line, id]
737
+
738
+ when 'return', 'end'
739
+ if @frames.size == @finish_pos
740
+ @stop_next = 1
741
+ @finish_pos = 0
742
+ end
743
+ @frames.shift
744
+
745
+ when 'end'
746
+ @frames.shift
747
+
748
+ when 'raise'
749
+ excn_handle(file, line, id, binding)
750
+
751
+ end
752
+ @last_file = file
753
+ end
754
+ end
755
+
756
+ trap("INT") { DEBUGGER__.interrupt }
757
+ @last_thread = Thread::main
758
+ @max_thread = 1
759
+ @thread_list = {Thread::main => 1}
760
+ @break_points = []
761
+ @display = []
762
+ @waiting = []
763
+ @stdout = STDOUT
764
+
765
+ class << DEBUGGER__
766
+ def stdout
767
+ @stdout
768
+ end
769
+
770
+ def stdout=(s)
771
+ @stdout = s
772
+ end
773
+
774
+ def display
775
+ @display
776
+ end
777
+
778
+ def break_points
779
+ @break_points
780
+ end
781
+
782
+ def waiting
783
+ @waiting
784
+ end
785
+
786
+ def set_trace( arg )
787
+ saved_crit = Thread.critical
788
+ Thread.critical = true
789
+ make_thread_list
790
+ for th, in @thread_list
791
+ context(th).set_trace arg
792
+ end
793
+ Thread.critical = saved_crit
794
+ arg
795
+ end
796
+
797
+ def set_last_thread(th)
798
+ @last_thread = th
799
+ end
800
+
801
+ def suspend
802
+ saved_crit = Thread.critical
803
+ Thread.critical = true
804
+ make_thread_list
805
+ for th, in @thread_list
806
+ next if th == Thread.current
807
+ context(th).set_suspend
808
+ end
809
+ Thread.critical = saved_crit
810
+ # Schedule other threads to suspend as soon as possible.
811
+ Thread.pass unless Thread.critical
812
+ end
813
+
814
+ def resume
815
+ saved_crit = Thread.critical
816
+ Thread.critical = true
817
+ make_thread_list
818
+ for th, in @thread_list
819
+ next if th == Thread.current
820
+ context(th).clear_suspend
821
+ end
822
+ waiting.each do |th|
823
+ th.run
824
+ end
825
+ waiting.clear
826
+ Thread.critical = saved_crit
827
+ # Schedule other threads to restart as soon as possible.
828
+ Thread.pass
829
+ end
830
+
831
+ def context(thread=Thread.current)
832
+ c = thread[:__debugger_data__]
833
+ unless c
834
+ thread[:__debugger_data__] = c = Context.new
835
+ end
836
+ c
837
+ end
838
+
839
+ def interrupt
840
+ context(@last_thread).stop_next
841
+ end
842
+
843
+ def get_thread(num)
844
+ th = @thread_list.index(num)
845
+ unless th
846
+ @stdout.print "No thread ##{num}\n"
847
+ throw :debug_error
848
+ end
849
+ th
850
+ end
851
+
852
+ def thread_list(num)
853
+ th = get_thread(num)
854
+ if th == Thread.current
855
+ @stdout.print "+"
856
+ else
857
+ @stdout.print " "
858
+ end
859
+ @stdout.printf "%d ", num
860
+ @stdout.print th.inspect, "\t"
861
+ file = context(th).instance_eval{@file}
862
+ if file
863
+ @stdout.print file,":",context(th).instance_eval{@line}
864
+ end
865
+ @stdout.print "\n"
866
+ end
867
+
868
+ def thread_list_all
869
+ for th in @thread_list.values.sort
870
+ thread_list(th)
871
+ end
872
+ end
873
+
874
+ def make_thread_list
875
+ hash = {}
876
+ for th in Thread::list
877
+ if @thread_list.key? th
878
+ hash[th] = @thread_list[th]
879
+ else
880
+ @max_thread += 1
881
+ hash[th] = @max_thread
882
+ end
883
+ end
884
+ @thread_list = hash
885
+ end
886
+
887
+ def debug_thread_info(input, binding)
888
+ case input
889
+ when /^l(?:ist)?/
890
+ make_thread_list
891
+ thread_list_all
892
+
893
+ when /^c(?:ur(?:rent)?)?$/
894
+ make_thread_list
895
+ thread_list(@thread_list[Thread.current])
896
+
897
+ when /^(?:sw(?:itch)?\s+)?(\d+)/
898
+ make_thread_list
899
+ th = get_thread($1.to_i)
900
+ if th == Thread.current
901
+ @stdout.print "It's the current thread.\n"
902
+ else
903
+ thread_list(@thread_list[th])
904
+ context(th).stop_next
905
+ th.run
906
+ return :cont
907
+ end
908
+
909
+ when /^stop\s+(\d+)/
910
+ make_thread_list
911
+ th = get_thread($1.to_i)
912
+ if th == Thread.current
913
+ @stdout.print "It's the current thread.\n"
914
+ elsif th.stop?
915
+ @stdout.print "Already stopped.\n"
916
+ else
917
+ thread_list(@thread_list[th])
918
+ context(th).suspend
919
+ end
920
+
921
+ when /^resume\s+(\d+)/
922
+ make_thread_list
923
+ th = get_thread($1.to_i)
924
+ if th == Thread.current
925
+ @stdout.print "It's the current thread.\n"
926
+ elsif !th.stop?
927
+ @stdout.print "Already running."
928
+ else
929
+ thread_list(@thread_list[th])
930
+ th.run
931
+ end
932
+ end
933
+ end
934
+
935
+ def start_debugger
936
+ stdout.printf "Debug.rb\n"
937
+ stdout.printf "Emacs support available.\n\n"
938
+ set_trace_func proc { |event, file, line, id, binding, klass, *rest|
939
+ DEBUGGER__.context.trace_func event, file, line, id, binding, klass
940
+ }
941
+ end
942
+ end
943
+
944
+ end