rfs 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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