lib/tracer.rb
DEFINITIONS
This source file includes following functions.
1 #
2 # tracer.rb -
3 # $Release Version: 0.2$
4 # $Revision: 1.8 $
5 # $Date: 1998/05/19 03:42:49 $
6 # by Keiju ISHITSUKA(Nippon Rational Inc.)
7 #
8 # --
9 #
10 #
11 #
12
13 #
14 # tracer main class
15 #
16 class Tracer
17 @RCS_ID='-$Id: tracer.rb,v 1.8 1998/05/19 03:42:49 keiju Exp keiju $-'
18
19 @stdout = STDOUT
20 @verbose = false
21 class << self
22 attr :verbose, true
23 alias verbose? verbose
24 attr :stdout, true
25 end
26
27 MY_FILE_NAME = caller(0)[0].scan(/^(.*):[0-9]+$/)[0][0]
28
29 EVENT_SYMBOL = {
30 "line" => "-",
31 "call" => ">",
32 "return" => "<",
33 "class" => "C",
34 "end" => "E",
35 "c-call" => ">",
36 "c-return" => "<",
37 }
38
39 def initialize
40 @threads = Hash.new
41 if defined? Thread.main
42 @threads[Thread.main.id] = 0
43 else
44 @threads[Thread.current.id] = 0
45 end
46
47 @get_line_procs = {}
48
49 @filters = []
50 end
51
52 def stdout
53 Tracer.stdout
54 end
55
56 def on
57 if block_given?
58 on
59 begin
60 yield
61 ensure
62 off
63 end
64 else
65 set_trace_func proc{|event, file, line, id, binding, klass, *rest|
66 trace_func event, file, line, id, binding, klass
67 }
68 stdout.print "Trace on\n" if Tracer.verbose?
69 end
70 end
71
72 def off
73 set_trace_func nil
74 stdout.print "Trace off\n" if Tracer.verbose?
75 end
76
77 def add_filter(p = proc)
78 @filters.push p
79 end
80
81 def set_get_line_procs(file, p = proc)
82 @get_line_procs[file] = p
83 end
84
85 def get_line(file, line)
86 if p = @get_line_procs[file]
87 return p.call(line)
88 end
89
90 unless list = SCRIPT_LINES__[file]
91 begin
92 f = open(file)
93 begin
94 SCRIPT_LINES__[file] = list = f.readlines
95 ensure
96 f.close
97 end
98 rescue
99 SCRIPT_LINES__[file] = list = []
100 end
101 end
102 if l = list[line - 1]
103 l
104 else
105 "-\n"
106 end
107 end
108
109 def get_thread_no
110 if no = @threads[Thread.current.id]
111 no
112 else
113 @threads[Thread.current.id] = @threads.size
114 end
115 end
116
117 def trace_func(event, file, line, id, binding, klass)
118 return if file == MY_FILE_NAME
119
120 for p in @filters
121 return unless p.call event, file, line, id, binding, klass
122 end
123
124 Thread.critical = true
125 stdout.printf("#%d:%s:%d:%s:%s: %s",
126 get_thread_no,
127 file,
128 line,
129 klass || '',
130 EVENT_SYMBOL[event],
131 get_line(file, line))
132 Thread.critical = false
133 end
134
135 Single = new
136 def Tracer.on
137 if block_given?
138 Single.on{yield}
139 else
140 Single.on
141 end
142 end
143
144 def Tracer.off
145 Single.off
146 end
147
148 def Tracer.set_get_line_procs(file_name, p = proc)
149 Single.set_get_line_procs(file_name, p)
150 end
151
152 def Tracer.add_filter(p = proc)
153 Single.add_filter(p)
154 end
155
156 end
157
158 SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
159
160 if caller(0).size == 1
161 if $0 == Tracer::MY_FILE_NAME
162 # direct call
163
164 $0 = ARGV[0]
165 ARGV.shift
166 Tracer.on
167 require $0
168 else
169 Tracer.on
170 end
171 end