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.
- data/MIT-LICENSE +7 -0
- data/Rakefile.rb +193 -0
- data/bin/RenameFileSet.rbw +14 -0
- data/bin/rfs.rb +214 -0
- data/bin/rfsd.rb +8 -0
- data/description.txt +24 -0
- data/lib/RenameFileSet.bak.rb +372 -0
- data/lib/errors.rb +15 -0
- data/lib/filters.rb +68 -0
- data/lib/gui.rb +216 -0
- data/lib/innate/array.rb +104 -0
- data/lib/innate/coverage.rb +315 -0
- data/lib/innate/debug.rb +12 -0
- data/lib/innate/debugger.rb +944 -0
- data/lib/innate/file.rb +5 -0
- data/lib/innate/filelines.rb +148 -0
- data/lib/innate/kernel.rb +41 -0
- data/lib/innate/metaid.rb +30 -0
- data/lib/innate/mkdirs.rb +12 -0
- data/lib/innate/regexp.rb +80 -0
- data/lib/innate/reload.rb +11 -0
- data/lib/innate/roman.rb +72 -0
- data/lib/innate/scriptlines.rb +60 -0
- data/lib/innate/string.rb +56 -0
- data/lib/innate/test/all_tests.rb +11 -0
- data/lib/innate/test/files/mkdirs_dummy.file +1 -0
- data/lib/innate/test/files/reloadtarget.rb +5 -0
- data/lib/innate/test/files/reloadtarget1.rb +5 -0
- data/lib/innate/test/files/reloadtarget2.rb +5 -0
- data/lib/innate/test/test_coverage.rb +13 -0
- data/lib/innate/test/testarray.rb +98 -0
- data/lib/innate/test/testfile.rb +15 -0
- data/lib/innate/test/testfilelines.rb +106 -0
- data/lib/innate/test/testkernel.rb +30 -0
- data/lib/innate/test/testmkdirs.rb +19 -0
- data/lib/innate/test/testregexp.rb +86 -0
- data/lib/innate/test/testreload.rb +61 -0
- data/lib/innate/test/testroman.rb +54 -0
- data/lib/innate/test/testscriptlines.rb +39 -0
- data/lib/innate/test/teststring.rb +52 -0
- data/lib/innate/test/testtitlecase.rb +20 -0
- data/lib/innate/titlecase.rb +64 -0
- data/lib/innate/tracerequire.rb +22 -0
- data/lib/namesource.rb +53 -0
- data/lib/options.rb +64 -0
- data/lib/providers.rb +93 -0
- data/lib/regexp.rb +56 -0
- data/lib/rename_functions.rb +142 -0
- data/lib/renamer.rb +210 -0
- data/lib/results.rb +83 -0
- data/lib/test/test_helper.rb +147 -0
- data/tests/dir/file1 +0 -0
- data/tests/dir/file2 +0 -0
- data/tests/dir/file3 +0 -0
- data/tests/test_helper.rb +147 -0
- data/tests/test_rename_functions.rb +605 -0
- metadata +105 -0
data/lib/innate/debug.rb
ADDED
@@ -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
|