XDCC-Fetch 1.386 → 1.409

Sign up to get free protection for your applications and to get access to all the features.
@@ -31,7 +31,7 @@ $cfg = Recursive_Open_Struct.new
31
31
  $cfg.app.name = "XDCC-Fetch"
32
32
  $cfg.app.version = "STONEAGE"
33
33
 
34
- $cfg.app.revision = "1.386"
34
+ $cfg.app.revision = "1.409"
35
35
 
36
36
  $cfg.app.developers = [
37
37
  "Martin Ankerl (GUI)",
@@ -88,13 +88,15 @@ $cfg.icons.about = "idea.png"
88
88
  $cfg.icons.cancel = "cancel.png"
89
89
  $cfg.icons.error_big = "messagebox_critical.png"
90
90
  $cfg.icons.warning_big = "messagebox_warning.png"
91
+ $cfg.icons.translations = "locale.png"
91
92
 
92
93
  # parameters for network code
93
- $cfg.network.tcp.connect_timeout = 5
94
+ $cfg.network.tcp.connect_timeout = 30
94
95
  $cfg.network.tcp.connect_thread_priority = -2
95
96
  $cfg.network.dcc.send_regexp = /^DCC\sSEND\s(\S+)\s(\d+)\s(\d+)\s(\d+)$/i
96
97
  $cfg.network.dcc.accept_regexp = /^DCC\sACCEPT\s(\S+\s)?\s*(\d+)\s(\d+)$/i
97
- $cfg.network.dcc.verification_bytes = 5000
98
+ $cfg.network.dcc.enable_verification = true
99
+ $cfg.network.dcc.verification_bytes = 20_000
98
100
  $cfg.network.dcc.block_nonroutable_addresses = true
99
101
  $cfg.network.ctcp.enable_replies = true
100
102
  $cfg.network.irc.default_port = 6667
@@ -134,5 +136,7 @@ Dir['src/Translations/*.rb'].each do |language_file|
134
136
  require language_file
135
137
  end
136
138
 
139
+ $cfg.text = Recursive_Open_Struct.new
140
+
137
141
  # prevent further modifications
138
142
  $cfg.close
@@ -2,8 +2,6 @@
2
2
  # Copyright:: Copyright (c) 2004-2005 Martin Ankerl
3
3
  # License:: BSD
4
4
  #
5
- # All rights reserved.
6
- #
7
5
  # Redistribution and use in source and binary forms, with or without modification,
8
6
  # are permitted provided that the following conditions are met:
9
7
  #
@@ -24,6 +22,7 @@
24
22
  # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25
23
  # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26
24
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ #
27
26
 
28
27
 
29
28
  # Recursive_Open_Struct provides a convenient interface to a hierarchy of configuration
@@ -56,22 +55,27 @@ class Recursive_Open_Struct
56
55
  end
57
56
 
58
57
  # automatically add parameters
59
- def method_missing(method, params=nil) # :nodoc:
58
+ def method_missing(method, *params) # :nodoc:
59
+ # setting or getting?
60
+ is_setting = !params.empty?
61
+
60
62
  key = method.id2name
61
- key.chop! if params # remove trailing =
63
+ # remove trailing =
64
+ key.chop! if is_setting
62
65
 
63
66
  # if structure is closed, disable hierarchy creation
64
- super if !@methods.has_key?(key) && !@open
67
+ super unless @methods.has_key?(key) || @open
65
68
 
66
- if params.nil?
67
- # no param: create new Recursive_Open_Struct object
68
- @methods[key] ||= Recursive_Open_Struct.new
69
- else
69
+ if is_setting
70
70
  # assigning a new value
71
71
  if @methods[key].class == Recursive_Open_Struct
72
72
  raise TypeError, "overwriting previously created hierarchy entry '#{key}' not allowed", caller(1)
73
- else
74
- @methods[key] = params
73
+ end
74
+ @methods[key] = *params
75
+ else
76
+ # no param: create new Recursive_Open_Struct object, if nothing is set.
77
+ unless @methods.has_key?(key)
78
+ @methods[key] = Recursive_Open_Struct.new
75
79
  end
76
80
  end
77
81
  @methods[key]
@@ -157,3 +161,98 @@ class Recursive_Open_Struct
157
161
  @open = status
158
162
  end
159
163
  end
164
+
165
+ if __FILE__ == $0
166
+ require 'test/unit'
167
+
168
+ class TestRecursiveOpenStruct < Test::Unit::TestCase
169
+ def setup
170
+ @s = Recursive_Open_Struct.new
171
+ end
172
+
173
+ def setAndAssertValue(val)
174
+ @s.test = val
175
+ assert_equal(val, @s.test)
176
+ @s.close
177
+ assert_equal(val, @s.test)
178
+ @s.test = "asdf"
179
+ assert_equal("asdf", @s.test)
180
+ end
181
+
182
+ def testSetNil
183
+ setAndAssertValue(nil)
184
+ end
185
+
186
+ def testSimple
187
+ @s.test = "xx"
188
+ @s.close
189
+ assert_equal("xx", @s.test)
190
+ end
191
+
192
+ def testSetFalse
193
+ setAndAssertValue(false)
194
+ end
195
+
196
+ def testSetStr
197
+ setAndAssertValue("topfen")
198
+ end
199
+
200
+ def testSetClass
201
+ setAndAssertValue(String)
202
+ end
203
+
204
+ def testSetTrue
205
+ setAndAssertValue(true)
206
+ end
207
+
208
+ def testSet0
209
+ setAndAssertValue(0)
210
+ end
211
+
212
+ def testRaiseTypeError
213
+ @s.a.b = 1
214
+ assert_raise(TypeError) do
215
+ @s.a = 3
216
+ end
217
+ end
218
+
219
+ def testAttrs
220
+ assert_equal([], @s.attrs)
221
+ @s.b = "x"
222
+ @s.a = "a"
223
+ assert_equal(["a", "b"], @s.attrs)
224
+ end
225
+
226
+ def testRecursive
227
+ @s.a.b = 1
228
+ @s.a.c = 2
229
+ assert_equal(["a"], @s.attrs)
230
+ end
231
+
232
+ def testStrange
233
+ @s.a
234
+ assert_equal(["a"], @s.attrs)
235
+ assert_equal(Recursive_Open_Struct, @s.a.class)
236
+ @s.a.x = "asfd"
237
+ assert_equal("asfd", @s.a.x)
238
+ end
239
+
240
+ def testKlammer
241
+ @s.a = "asdf"
242
+ assert_equal("asdf", @s["a"])
243
+ @s.b_x = "hog"
244
+ assert_equal("hog", @s["b_x"])
245
+ @s.c.b.a = 1234
246
+ assert_equal(1234, @s["c"]["b"]["a"])
247
+ end
248
+
249
+ def testDeep
250
+ @s.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = false
251
+ @s.close
252
+ assert_raise(NoMethodError) do
253
+ @s.blub = "hellow"
254
+ end
255
+ assert_equal(false, @s.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z)
256
+ end
257
+ end
258
+ end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.4
3
3
  specification_version: 1
4
4
  name: XDCC-Fetch
5
5
  version: !ruby/object:Gem::Version
6
- version: "1.386"
7
- date: 2005-01-30
6
+ version: "1.409"
7
+ date: 2005-02-13
8
8
  summary: "XDCC-Fetch, written entirely in Ruby, is an intuitive, no-nonsense tool for
9
9
  searching, collecting and downloading XDCC announcements within IRC channels.
10
10
  XDCC-Fetch is released under the BSD license and available for free."
@@ -34,46 +34,46 @@ files:
34
34
  - "./icons"
35
35
  - "./icons/package.png"
36
36
  - "./icons/camera_test.png"
37
+ - "./icons/cancel.png"
38
+ - "./icons/connect_no.png"
37
39
  - "./icons/messagebox_warning.png"
38
- - "./icons/package_favourite.png"
40
+ - "./icons/ark.png"
39
41
  - "./icons/folder_inbox.png"
40
- - "./icons/package_unknown.png"
41
42
  - "./icons/messagebox_warning_small.png"
42
- - "./icons/connect_no.png"
43
- - "./icons/ark.png"
44
- - "./icons/messagebox_critical.png"
43
+ - "./icons/package_unknown.png"
45
44
  - "./icons/exit.png"
46
- - "./icons/cancel.png"
47
- - "./icons/mega_ark.png"
48
- - "./icons/fileclose.png"
49
45
  - "./icons/messagebox_info.png"
50
- - "./icons/idea.png"
51
- - "./icons/edit_remove.png"
46
+ - "./icons/package_favourite.png"
47
+ - "./icons/fileclose.png"
52
48
  - "./icons/connect_creating.png"
49
+ - "./icons/messagebox_critical.png"
50
+ - "./icons/connect_established.png"
51
+ - "./icons/mega_ark.png"
52
+ - "./icons/idea.png"
53
+ - "./icons/locale.png"
54
+ - "./icons/connect_failed.png"
53
55
  - "./icons/ark_big.png"
54
56
  - "./icons/edit_add.png"
55
- - "./icons/connect_failed.png"
56
- - "./icons/connect_established.png"
57
+ - "./icons/edit_remove.png"
57
58
  - "./src"
58
59
  - "./src/Utilities"
59
- - "./src/Utilities/PrettyException.rb"
60
60
  - "./src/Utilities/Recursive_Open_Struct.rb"
61
61
  - "./src/Utilities/Events.rb"
62
62
  - "./src/Utilities/Configuration.rb"
63
63
  - "./src/Utilities/Timer.rb"
64
64
  - "./src/Utilities/Globals.rb"
65
65
  - "./src/Network"
66
- - "./src/Network/XDCC_Announcement.rb"
67
66
  - "./src/Network/IRC_User.rb"
68
- - "./src/Network/DCC_File.rb"
67
+ - "./src/Network/XDCC_Announcement.rb"
69
68
  - "./src/Network/CTCP_Handler.rb"
69
+ - "./src/Network/DCC_Parser.rb"
70
70
  - "./src/Network/XDCC_Download_Handler.rb"
71
71
  - "./src/Network/IRC_Server_Respond_Map.rb"
72
- - "./src/Network/DCC_Parser.rb"
73
- - "./src/Network/IRC_Server.rb"
74
72
  - "./src/Network/IPAddr_Ext.rb"
75
- - "./src/Network/XDCC_Announcement_Storage.rb"
73
+ - "./src/Network/IRC_Server.rb"
76
74
  - "./src/Network/IRC_Message.rb"
75
+ - "./src/Network/XDCC_Announcement_Storage.rb"
76
+ - "./src/Network/DCC_File.rb"
77
77
  - "./src/Network/XDCC_Pack.rb"
78
78
  - "./src/Network/XDCC_Parser.rb"
79
79
  - "./src/Network/TCP_Connection.rb"
@@ -82,16 +82,17 @@ files:
82
82
  - "./src/GUI/Talk_Back.rb"
83
83
  - "./src/GUI/Application_Builder.rb"
84
84
  - "./src/GUI/Main_Window.rb"
85
- - "./src/GUI/About_Dialog.rb"
86
- - "./src/GUI/Download_Finished_Box.rb"
87
85
  - "./src/GUI/Context_Menu.rb"
88
86
  - "./src/GUI/Dialog_Box.rb"
89
- - "./src/GUI/Packet_Item.rb"
90
- - "./src/GUI/Custom_Tabs.rb"
91
87
  - "./src/GUI/Empty_Text_Field_Handler.rb"
92
88
  - "./src/GUI/Speed_Widget.rb"
93
89
  - "./src/GUI/Packet_List.rb"
94
90
  - "./src/GUI/Gui_Logic.rb"
91
+ - "./src/GUI/Search_Engine.rb"
92
+ - "./src/GUI/Download_Finished_Box.rb"
93
+ - "./src/GUI/About_Dialog.rb"
94
+ - "./src/GUI/Packet_Item.rb"
95
+ - "./src/GUI/Custom_Tabs.rb"
95
96
  - "./src/GUI/Icon_Loader.rb"
96
97
  - "./src/Console"
97
98
  - "./src/Console/XDCC_Pack_Match_Template.rb"
@@ -100,6 +101,7 @@ files:
100
101
  - "./src/Translations"
101
102
  - "./src/Translations/check_translations"
102
103
  - "./src/Translations/README"
104
+ - "./src/Translations/pl.rb"
103
105
  - "./src/Translations/de.rb"
104
106
  - "./src/Translations/en.rb"
105
107
  - "./XDCC-Fetch.rbw"
@@ -1,1091 +0,0 @@
1
- ###################################################
2
- # # # # # # # # # # # # # # # # # # # # # # # # # #
3
- #
4
- # = lib/PrettyException.rb
5
- #
6
- # PrettyPrint for Exceptions
7
- #
8
- # Author:: Dmitry V. Sabanin <sdmitry@lrn.ru>
9
- # Revision:: $Date: 2004/12/20 05:11:50 $ $Revision: 1.16 $
10
- # License:: LGPL
11
- #
12
- # Modified to use rdoc's templating by Michael Neumann (mneumann@ntecs.de).
13
- #
14
- # # # # # # # # # # # # # # # # # # # # # # # # # #
15
- ###################################################
16
-
17
- require 'rdoc/template'
18
- require 'rbconfig'
19
- require 'cgi'
20
-
21
- ###################################################
22
- # Web PrettyPrint for Exceptions
23
- #
24
- class PrettyException
25
-
26
- attr_writer :message
27
-
28
- ###################################################
29
- def initialize(exception, tplpath = nil)
30
- @tplpath = tplpath
31
- @exception = exception
32
- @message = nil
33
- end
34
- ###################################################
35
-
36
- ###################################################
37
- def build_template
38
- tmpl =
39
- if @tplpath and File.exists?(@tplpath)
40
- File.read(@tplpath)
41
- else
42
- tplfile = File.readlines(__FILE__)
43
- start = nil
44
- tplfile.each_with_index do |line,idx|
45
- if line =~ /^__END__\s*$/
46
- start = idx + 1
47
- break
48
- end
49
- end
50
- tplfile[start..-1].join('')
51
- end
52
-
53
- return TemplatePage.new(tmpl)
54
- end
55
- ###################################################
56
-
57
- ###################################################
58
- def gen_source(file, line, mark_line = true)
59
- source = File.readlines(file)
60
- source = hilite_source(source)
61
- line = line.to_i
62
- if mark_line
63
- show = 3
64
- begin_from = line - show
65
- end_at = line + show
66
- begin_from = begin_from > 0 ? begin_from : 0
67
- work_with = source[begin_from..end_at]
68
- else
69
- work_with = [ source[line-1] ]
70
- end
71
- work_with ||= []
72
- res = []
73
- work_with.each do |i, l|
74
- l = ('<span class="hl_lineno">%.3d:</span>%s' % [i," "]) + l
75
- if i == line and mark_line
76
- buf = '<div class="current_line">' + l + '</div>'
77
- else
78
- buf = l + "\n"
79
- end
80
- res << buf
81
- end
82
- res.join
83
- end
84
- ###################################################
85
-
86
- ###################################################
87
- def hilite_source(src)
88
- lx = LexerRuby::LexerOld.new
89
- src.each do |sline|
90
- lx.lex_line(sline)
91
- end
92
- res = []
93
- lineno = 0
94
- this_line = []
95
- hc = false
96
- heredoc_buf = nil
97
- lx.result.each do |text, token|
98
- if hc
99
- lineno += 1
100
- res << [lineno, this_line.join]
101
- this_line = []
102
- hc = false
103
- end
104
- if token != :heredoc and heredoc_buf and token != :any
105
- heredoc = heredoc_buf.split(/\n/)
106
- heredoc.each do |hd_line|
107
- res << [lineno, ('<span class="hl_heredoc">%s</span>' % [hd_line.to_s])]
108
- lineno += 1
109
- end
110
- this_line = []
111
- heredoc_buf = nil
112
- end
113
- case token
114
- when :keyword, :ident, :punct,
115
- :comment, :ivar, :dot,
116
- :string, :command, :number,
117
- :gvar, :literal, :symbol
118
- if token == :comment
119
- hc = true
120
- end
121
- text = CGI.escapeHTML(text)
122
- this_line << ('<span class="hl_%s">%s</span>' % [token.to_s, text.rstrip])
123
- when :heredoc
124
- text = CGI.escapeHTML(text)
125
- heredoc_buf ||= ''
126
- heredoc_buf << text
127
- when :any
128
- if text =~ /^\s*\n$/
129
- lineno += 1
130
- res << [lineno, this_line.join]
131
- this_line = []
132
- else
133
- this_line << text
134
- end
135
- else
136
- this_line << CGI.escapeHTML(text)
137
- end
138
- end
139
- res << [lineno+1, this_line.join] if this_line.length > 0
140
- res
141
- end
142
- ###################################################
143
-
144
- ###################################################
145
- def print
146
- tpl = build_template
147
- contents = {}
148
- contents['message'] = CGI::escapeHTML(@exception.message).to_s
149
- contents['exception'] = @exception.class.to_s
150
- contents['time'] = Time.now.to_s
151
- bt = []
152
- @exception.backtrace.each_with_index do |str,idx|
153
- file,text = str.scan(/^(.+):(.+)(?::(.+))?$/).flatten;
154
- file,line = file.split(/:/)
155
- unless line
156
- line = text
157
- text = nil
158
- end
159
- is_stdlib = false
160
- paths = [Config::CONFIG['rubylibdir'], Config::CONFIG['sitedir']]
161
- paths.each do |dir|
162
- is_stdlib = true if (file =~ /#{Regexp::escape(dir)}/)
163
- end
164
- data = { 'file' => file, 'line' => line, 'text' => text, 'from_stdlib' => is_stdlib }
165
- if idx == 0
166
- data['source'] = gen_source(file, line)
167
- else
168
- data['source'] = gen_source(file, line)
169
- end
170
- data['iteration_id'] = idx.to_s
171
- bt << data
172
- end
173
- contents['backtrace'] = bt
174
- tpl.write_html_on(output='', contents)
175
- output
176
- end
177
- ###################################################
178
-
179
- alias_method :to_s, :print
180
-
181
- end
182
-
183
- class LexerBase
184
- def initialize
185
- @states = []
186
- @result = []
187
- @result_endofline = nil
188
- end
189
- attr_reader :states, :result, :result_endofline
190
-
191
- def set_states(states)
192
- @states = states
193
- end
194
- def set_result(result)
195
- @result = result
196
- end
197
- def format(text, state_output)
198
- @result << [text, state_output]
199
- end
200
- def format_end(state_output)
201
- @result_endofline = state_output
202
- end
203
- def match(regexp, output)
204
- m = regexp.match(@text)
205
- return false unless m
206
- txt = @text.slice!(0, m.end(0))
207
- format(txt, output)
208
- true
209
- end
210
- def lex_line(text)
211
- raise "derived class #{self.class} must overload #lex_line."
212
- end
213
- def self.profile
214
- lines = IO.readlines(__FILE__)
215
- lexer = self.new
216
- puts "profiling the #{self.inspect} lexer (this may take some time)"
217
- require 'profiler'
218
- Profiler__.start_profile
219
- lines.each do |line|
220
- lexer.set_states([])
221
- lexer.set_result([])
222
- lexer.lex_line(line)
223
- end
224
- Profiler__.print_profile(STDOUT)
225
- end
226
- def self.benchmark
227
- n = 10000
228
- puts "benchmarking the lexers (computing #{n} lines " +
229
- "with GC disabled)"
230
- require 'benchmark'
231
- Benchmark.bm(20) do |b|
232
- lexer = LexerRuby::LexerOld.new
233
- #=begin
234
- lines = IO.readlines(__FILE__)
235
- GC.disable
236
- b.report("#{lexer.class}") do
237
- n.times do |i|
238
- lexer.set_states([])
239
- lexer.set_result([])
240
- lexer.lex_line(lines[i%lines.size].clone)
241
- end
242
- end
243
- #=begin
244
- GC.enable
245
- GC.start
246
- lines = IO.readlines(__FILE__)
247
- lexer = LexerRuby::LexerNew.new
248
- GC.disable
249
- b.report("#{lexer.class}") do
250
- n.times do |i|
251
- lexer.set_states([])
252
- lexer.set_result([])
253
- lexer.lex_line(lines[i%lines.size])
254
- end
255
- end
256
- =begin
257
- =end
258
- GC.enable
259
- GC.start
260
- lines = IO.readlines(__FILE__)
261
- lexer = LexerRuby::Lexer3.new
262
- GC.disable
263
- b.report("#{lexer.class}") do
264
- n.times do |i|
265
- lexer.set_states([])
266
- lexer.set_result([])
267
- lexer.lex_line(lines[i%lines.size])
268
- end
269
- end
270
- GC.enable
271
- end
272
- end
273
- end
274
-
275
- module LexerText
276
-
277
- class Lexer < LexerBase
278
- RE_TAB = /\A\t+/
279
- RE_NOTTAB = /\A[^\t]+/
280
- def lex_line(text)
281
- @text = text
282
- until @text.empty?
283
- if match(RE_TAB, :tab)
284
- else
285
- match(RE_NOTTAB, :text)
286
- end
287
- end
288
- end
289
- end # class Lexer
290
-
291
- end # module LexerText
292
-
293
- module LexerRuby
294
-
295
- module State
296
-
297
- class Base
298
- end
299
-
300
- class Heredoc < Base
301
- def initialize(begin_tag, ignore_leading_spaces, interpolate=true)
302
- @begin_tag = begin_tag
303
- @ignore_leading_spaces = ignore_leading_spaces
304
- @interpolate = interpolate
305
- end
306
- attr_reader :begin_tag, :ignore_leading_spaces, :interpolate
307
- def ==(other)
308
- (self.class == other.class) and
309
- (@begin_tag == other.begin_tag) and
310
- (@ignore_leading_spaces == other.ignore_leading_spaces) and
311
- (@interpolate == other.interpolate)
312
- end
313
- end
314
-
315
- class Comment < Base
316
- def ==(other)
317
- (self.class == other.class)
318
- end
319
- end
320
-
321
- class Endoffile < Base
322
- def ==(other)
323
- (self.class == other.class)
324
- end
325
- end
326
-
327
- end # module State
328
-
329
- class NewerRubyLexer
330
- RE_TOKENIZE = Regexp.new([
331
- # TODO: @ivar
332
- # TODO: @@cvar
333
- # TODO: $gvar
334
- # TODO: %literals %w(a b c) %Q|'"|
335
- # TODO: :symbol
336
- # TODO: ?x chars
337
- # TODO: 0b01001 binary data
338
- # TODO: 0x234af hex data
339
- # TODO: keywords =begin defined?
340
- # TODO: ruby puncturation .. ... && ||
341
- # TODO: /regexp/
342
- # TODO: __END__ tag
343
- # TODO: illegal ruby heredoc which has space after end-tag
344
- # TODO: illegal ruby puncturation &&& |||
345
- # TODO: illegal ruby numbers 0x23Yab
346
- '#.*', # # blah ## !?! comment
347
- '<<-?[[:alpha:]]+', # <<HTML <<-XML heredoc
348
- '<<-?\'[[:alpha:]]+\'', # <<'eof' <<-'X' heredoc single quoted
349
- '<<-?"[[:alpha:]]+"', # <<"eof" <<-"X" heredoc double quoted
350
- '\.[[:alpha:]][[:alnum:]_]*', # .method .dup2 method call
351
- '[[:alpha:]][[:alnum:]_]*', # value pix2_3 identifier
352
- '\'(?:[^\\\\]|\\\\.)*?\'', # '\'x\\' '' string single quoted
353
- '"(?:[^\\\\]|\\\\.)*?"', # "ab" "" string double quoted
354
- '\d+\.\d+', # 0.123 32.10 number as float
355
- '\d+', # 42 999 number as integer
356
- '.' # * + fallthrough
357
- ].join('|'))
358
- def initialize
359
- @char_to_symbol_hash = {
360
- " " => :space,
361
- "\t" => :tab
362
- }
363
- @char_to_symbol_hash.default = :should_not_happen
364
- end
365
- def tokenize(string)
366
- string.scan(RE_TOKENIZE)
367
- end
368
- def lex(string)
369
- tokens = tokenize(string)
370
- states = tokens.map do |token|
371
- # TODO: by inserting 2 parentesises in the TOKENIZER
372
- # then I can destinguish between good/bad tokens.
373
- # 'ab'.scan(/(a)(b)/) do |(good, bad)|
374
- case token
375
- when /\A(?:"|')./
376
- :string
377
- when /\A<<-?(?:"|'|)[[:alpha:]]/
378
- :heredoc
379
- when /\A\.[[:alpha:]]/
380
- :method
381
- when /\A[[:alpha:]]/
382
- :ident
383
- when /\A#/
384
- :comment
385
- when /\A[[:punct:]]/
386
- :punct
387
- when /\A[[:digit:]]/
388
- :number
389
- else
390
- @char_to_symbol_hash[token]
391
- end
392
- end
393
- [tokens, states]
394
- end
395
- end
396
-
397
- class Lexer3 < LexerBase
398
- def initialize
399
- @rl = NewerRubyLexer.new
400
- super
401
- end
402
- def what_to_output(hash)
403
- @rl.what_to_output(hash)
404
- end
405
- def lex_line(text)
406
- tokens, states = @rl.lex(text)
407
- tokens.each_with_index do |token, index|
408
- format(token, states[index])
409
- end
410
- true
411
- end
412
- end
413
-
414
-
415
- class RubyLexer
416
- def initialize
417
- @result = []
418
- end
419
- attr_reader :result
420
- PUNCT = ['(', ')'] +
421
- %w(=== == =~ => = != !~ !) +
422
- %w(<< <=> <= < >= >) +
423
- %w({ } [ ]) +
424
- %w(:: : ... ..) +
425
- %w(+= + -= - ** * / %) +
426
- %w(|| | && &) +
427
- %w(, ;)
428
- RE_NUMBER = /\d[\d\.]*/
429
- RE_PUNCT = Regexp.new('(?:' +
430
- PUNCT.map{|i| Regexp.escape(i)}.join('|') + ')')
431
- RE_IDENT = /[[:alpha:]][\w\!]*/
432
- RE_STRING = /".*?"|'.*?'/
433
- RE_COMMENT = /#.*/
434
- RE_COMMAND = /\.[[:alnum:]_]*[[:alnum:]_\?\!]/
435
- RE_SPACE = /\x20+/
436
- RE_NEWLINE = /\n+/
437
- RE_TABS = /\t+/
438
- def scan_index(string, regexp, prio, symbol)
439
- string.scan(regexp) do
440
- @result << [$~.begin(0), prio, $~.end(0), symbol]
441
- end
442
- end
443
- def lex(string)
444
- scan_index(string, RE_COMMENT, 0, :comment)
445
- scan_index(string, RE_STRING, 1, :string)
446
- scan_index(string, RE_COMMAND, 2, :command)
447
- scan_index(string, RE_IDENT, 3, :ident)
448
- scan_index(string, RE_NUMBER, 4, :number)
449
- scan_index(string, RE_PUNCT, 5, :punct)
450
- scan_index(string, RE_SPACE, 6, :space)
451
- scan_index(string, RE_NEWLINE, 7, :newline)
452
- scan_index(string, RE_TABS, 8, :tabs)
453
- end
454
- def result
455
- # primary key = string begin position
456
- # secondary key = priority
457
- @result.sort!
458
- # collect the highest precedens data
459
- ary = [0]
460
- @result.each do |i1, prio, i2, symbol|
461
- next if ary.last > i1 # discard low precedens data
462
- if ary.last < i1
463
- ary << :any
464
- ary << i1
465
- end
466
- ary << symbol
467
- ary << i2
468
- end
469
- #p ary
470
- ary
471
- end
472
- def self.mk(*symbols)
473
- symbols.each do |symbol|
474
- class_eval %{
475
- def #{symbol.to_s}
476
- res = []
477
- @result.each do |i1, prio, i2, sym|
478
- if sym == :#{symbol.to_s}
479
- res << [i1, i2]
480
- end
481
- end
482
- res
483
- end
484
- }
485
- end
486
- end
487
- mk :number, :ident, :string, :punct
488
- mk :comment, :command, :space, :newline, :tabs
489
- end
490
-
491
- class LexerNew < LexerBase
492
- def lex_line(text)
493
- #puts("-"*40)
494
- #puts "text=#{text.inspect}"
495
- rl = RubyLexer.new
496
- rl.lex(text)
497
- res = rl.result
498
- #puts "res=#{res.inspect}"
499
- i1 = res.shift
500
- while res.size > 1
501
- symbol = res.shift
502
- i2 = res.shift
503
- format(text[i1, (i2-i1)], symbol)
504
- i1 = i2
505
- end
506
- #puts "result=#{@result.inspect}"
507
- true
508
- end
509
- end
510
-
511
- class LexerOld < LexerBase
512
- RE_COMMENT = /^#.*/m
513
-
514
- RE_TAB = /^\t+/
515
-
516
- RE_SPACE = /^\x20+/
517
-
518
- KEYWORDS = %w(alias and begin BEGIN break case class) +
519
- %w(defined? def do else elsif end END ensure for if loop) +
520
- %w(module next nil not or raise redo require rescue) +
521
- %w(retry return self super then true false undef) +
522
- %w(unless until yield when while)
523
- RE_KEYWORD = Regexp.new(
524
- '\A(?:' +
525
- KEYWORDS.map{|txt|Regexp.escape(txt)}.join('|') +
526
- ')(?!\w)'
527
- )
528
-
529
- RE_SYMBOL = /\A:[[:alpha:]_][[:alnum:]_]*/
530
-
531
- RE_STRING = /^("|\')(?:[^\\]|\\.)*?\1/
532
- RE_STRING_INTERPOL = /\A ((?:[^\\]|\\.)*?) (\#\{ .*? \}) /x
533
- # TODO: interpolated code can nest (hint: recursion is necessary)
534
- def match_string
535
- m = RE_STRING.match(@text)
536
- return false unless m
537
- txt = @text.slice!(0, m.end(0))
538
- if m[1] == '\''
539
- format(txt, :string)
540
- return true
541
- end
542
- # double quoted strings may contain interpolated code
543
- until txt.empty?
544
- m = RE_STRING_INTERPOL.match(txt)
545
- unless m
546
- format(txt, :string)
547
- break
548
- end
549
- format(m[1], :string) unless m[1].empty?
550
- format(m[2], :string1)
551
- txt.slice!(0, m.end(0))
552
- end
553
- true
554
- end
555
-
556
- RE_REGEXP = /\A\/(.*?[^\\])?\//
557
-
558
- RE_IVAR = /\A@[[:alnum:]_]+/
559
-
560
- RE_DOT = /\A\.[[:alnum:]_]*[[:alnum:]_\?\!]/
561
-
562
- RE_IDENTIFIER = /\A(?:[[:alnum:]_]+|\S+)/
563
-
564
- RE_NUMBER = Regexp.new(
565
- '\A(?:' + [
566
- '0x[_a-fA-F0-9]+',
567
- '0b[_01]+',
568
- '\d[0-9_]*(?:\.[0-9_]*)?',
569
- '\?.'
570
- ].join('|') +
571
- ')'
572
- )
573
-
574
- PUNCT = ['(', ')'] +
575
- %w(=== == =~ => = != !~ !) +
576
- %w(<< <=> <= < >= >) +
577
- %w({ } [ ]) +
578
- %w(:: : ... ..) +
579
- %w(+= + -= - ** * / %) +
580
- %w(|| | && &) +
581
- %w(, ;)
582
- RE_PUNCT = Regexp.new(
583
- '\A(?:' +
584
- PUNCT.map{|txt|Regexp.escape(txt)}.join('|') +
585
- ')'
586
- )
587
-
588
- VAR_GLOBALS = %q(_~*$!@/\\;,.=:<>"-&`'+1234567890).split(//)
589
- RE_GVAR = Regexp.new(
590
- '\A\$(?:' +
591
- VAR_GLOBALS.map{|txt|Regexp.escape(txt)}.join('|') +
592
- '|[[:alnum:]_]+' +
593
- ')'
594
- )
595
-
596
- # TODO: deal with multiline literals
597
- RE_LITERAL = Regexp.new(
598
- '\A%[Qqwrx]?(?:' + [
599
- '\(.*?\)', # TODO: must count pairs
600
- '\{.*?\}', # TODO: must count pairs
601
- '\<.*?\>', # TODO: must count pairs
602
- '\[.*?\]', # TODO: must count pairs
603
- '([^\(\{\<\[]).*?\1'
604
- ].join('|') + ')'
605
- )
606
-
607
- RE_BEGIN = /\A=begin$\n?\x20*\z/ # eat tailing space
608
- def match_comment_begin
609
- m = RE_BEGIN.match(@text)
610
- return false unless m
611
- #puts "comments"
612
- @states << State::Comment.new
613
- txt = @text.slice!(0, m.end(0))
614
- format(txt, :mcomment)
615
- format_end(:mcomment_end)
616
- true
617
- end
618
- RE_HEREDOC = /\A<<(-)?('|"|)(\w+)\2/
619
- def match_heredoc_begin
620
- m = RE_HEREDOC.match(@text)
621
- return false unless m
622
- ignore_leading_space = (m[1] != nil)
623
- interpolate = (m[2] != "'")
624
- begin_pattern = m[3]
625
- @states << State::Heredoc.new(
626
- begin_pattern,
627
- ignore_leading_space,
628
- interpolate
629
- )
630
- txt = @text.slice!(0, m.end(0))
631
- format(txt, :heredoc)
632
- true
633
- end
634
- RE_END = /\A__END__$\n?\x20*\z/ # eat tailing space
635
- def match_endoffile
636
- m = RE_END.match(@text)
637
- return false unless m
638
- #puts "propagate __END__"
639
- @states << State::Endoffile.new
640
- txt = @text.slice!(0, m.end(0))
641
- format(txt, :endoffile)
642
- format_end(:endoffile_end)
643
- true
644
- end
645
- def lex_line_normal(text)
646
- @text = text
647
- return if match_comment_begin
648
- return if match_endoffile
649
- until @text.empty?
650
- if match(RE_COMMENT, :comment)
651
- format_end(:comment_end)
652
- elsif match(RE_REGEXP, :regexp)
653
- elsif match_heredoc_begin
654
- elsif match(RE_LITERAL, :literal)
655
- elsif match(RE_KEYWORD, :keyword)
656
- elsif match(RE_SYMBOL, :symbol)
657
- elsif match(RE_PUNCT, :punct)
658
- elsif match(RE_GVAR, :gvar)
659
- elsif match_string
660
- elsif match(RE_NUMBER, :number)
661
- elsif match(RE_IVAR, :ivar)
662
- elsif match(RE_DOT, :dot)
663
- elsif match(RE_IDENTIFIER, :ident)
664
- elsif match(RE_TAB, :tab)
665
- elsif match(RE_SPACE, :space)
666
- else
667
- #@text.slice!(0, 1)
668
- txt = @text.slice!(0, 1)
669
- format(txt, :any)
670
- end
671
- end
672
- end
673
- def match_heredoc_end(regexp)
674
- m = regexp.match(@text)
675
- return false unless m
676
- #puts "end of heredoc"
677
- @states.shift
678
- txt = @text.slice!(0, m.end(0))
679
- format(txt, :heredoc)
680
- format_end(:heredoc_end2)
681
- true
682
- end
683
- def lex_line_heredoc(text)
684
- # TODO: color interpolated code #{code}
685
- @text = text
686
- format_end(:heredoc_end)
687
- hd_end = nil
688
- state = @states[0]
689
- hd_end = /\A#{state.begin_tag}$\n?\x20*\z/
690
- return if match_heredoc_end(hd_end)
691
- # continue lexing
692
- ign_lead_spc = state.ignore_leading_spaces
693
- until @text.empty?
694
- if match(RE_TAB, :heredoc_tab)
695
- elsif ign_lead_spc and match_heredoc_end(hd_end)
696
- else
697
- txt = @text.slice!(0, 1)
698
- format(txt, :heredoc)
699
- end
700
- end
701
- end
702
- def match_comment_end
703
- m = /\A\=end\b.*?$\n?\x20*\z/.match(@text)
704
- return false unless m
705
- #puts "comment end"
706
- @states.shift
707
- txt = @text.slice!(0, m.end(0))
708
- format(txt, :mcomment)
709
- true
710
- end
711
- def lex_line_comment(text)
712
- @text = text
713
- format_end(:mcomment_end)
714
- return if match_comment_end
715
- until @text.empty?
716
- if match(RE_TAB, :mcomment_tab)
717
- else
718
- txt = @text.slice!(0, 1)
719
- format(txt, :mcomment)
720
- end
721
- end
722
- end
723
- def lex_line_endoffile(text)
724
- @text = text
725
- format_end(:endoffile_end)
726
- until @text.empty?
727
- if match(RE_TAB, :endoffile_tab)
728
- else
729
- txt = @text.slice!(0, 1)
730
- format(txt, :endoffile)
731
- end
732
- end
733
- end
734
- def lex_line(text)
735
- if @states.empty?
736
- return lex_line_normal(text)
737
- end
738
- state = @states[0]
739
- case state
740
- when State::Heredoc: lex_line_heredoc(text)
741
- when State::Comment: lex_line_comment(text)
742
- when State::Endoffile: lex_line_endoffile(text)
743
- else
744
- raise "unknown state #{state.class}"
745
- end
746
- end
747
- end
748
-
749
- # TODO: make the new lexer work!
750
- Lexer = LexerOld # slow
751
- #Lexer = LexerNew # slow
752
- #Lexer = Lexer3 # fastest
753
-
754
- end # module LexerRuby
755
-
756
- __END__
757
- <html>
758
- <head>
759
- <title>Oops!</title>
760
- <style>
761
- .data {
762
- border-style: dotted;
763
- padding: 4px; }
764
- .trace_header {
765
- border-style: dotted;
766
- border-width: thin;
767
- background-color: #CCCCCC;
768
- text-align: center; }
769
- .normal_trace_entry {
770
- border-style: dotted;
771
- border-width: thin;
772
- text-align: center;
773
- padding: 6px; }
774
- .stdlib_trace_entry {
775
- border-style: dotted;
776
- border-width: thin;
777
- text-align: right;
778
- padding: 6px; }
779
- .source {
780
- width: 100%;
781
- background-color: #F4F4F4;
782
- display: none;
783
- }
784
- span.hl_lineno {
785
- font-weight: bold;
786
- }
787
- pre {
788
- width: 80%;
789
- padding: 0px;
790
- margin: 0px;
791
- }
792
- div.current_line {
793
- color: red;
794
- background-color: #F4DADA;
795
- }
796
- span.hl_keyword {
797
- font-weight: bold;
798
- }
799
- span.hl_punct {
800
- font-weight: bold;
801
- color: darkblue;
802
- }
803
- span.hl_ident {
804
- }
805
- span.hl_command {
806
- font-weight: bold;
807
- }
808
- span.hl_number {
809
- color: darkgreen;
810
- }
811
- span.hl_string {
812
- color: darkgreen;
813
- }
814
- span.hl_comment {
815
- color: grey;
816
- }
817
- span.hl_ivar {
818
- font-weight: bold;
819
- color: darkred;
820
- }
821
- span.hl_dot {
822
- font-weight: bold;
823
- }
824
- span.hl_literal {
825
- color: green;
826
- }
827
- span.hl_gvar {
828
- font-weight: bold;
829
- }
830
- span.hl_symbol {
831
- color: blue;
832
- }
833
- span.hl_regexp {
834
- color: green;
835
- }
836
- tr {
837
- background-color: white;
838
- }
839
- </style>
840
- <script type="text/javascript" language="javascript">
841
- function toggleCode( id ) {
842
- if ( document.getElementById )
843
- elem = document.getElementById( id );
844
- else if ( document.all )
845
- elem = eval( "document.all." + id );
846
- else
847
- return false;
848
-
849
- elemStyle = elem.style;
850
-
851
- if ( elemStyle.display != "block" ) {
852
- elemStyle.display = "block"
853
- } else {
854
- elemStyle.display = "none"
855
- }
856
-
857
- return true;
858
- }
859
-
860
- var isDOM = (typeof(document.getElementsByTagName) != 'undefined'
861
- && typeof(document.createElement) != 'undefined')
862
- ? 1 : 0;
863
- var isIE4 = (typeof(document.all) != 'undefined'
864
- && parseInt(navigator.appVersion) >= 4)
865
- ? 1 : 0;
866
- var isNS4 = (typeof(document.layers) != 'undefined')
867
- ? 1 : 0;
868
- var capable = (isDOM || isIE4 || isNS4)
869
- ? 1 : 0;
870
- // Uggly fix for Opera and Konqueror 2.2 that are half DOM compliant
871
- if (capable) {
872
- if (typeof(window.opera) != 'undefined') {
873
- var browserName = ' ' + navigator.userAgent.toLowerCase();
874
- if ((browserName.indexOf('konqueror 7') == 0)) {
875
- capable = 0;
876
- }
877
- } else if (typeof(navigator.userAgent) != 'undefined') {
878
- var browserName = ' ' + navigator.userAgent.toLowerCase();
879
- if ((browserName.indexOf('konqueror') > 0) && (browserName.indexOf('konqueror/3') == 0)) {
880
- capable = 0;
881
- }
882
- } // end if... else if...
883
- } // end if
884
-
885
- /**
886
- * This array is used to remember mark status of rows in browse mode
887
- */
888
- var marked_row = new Array;
889
-
890
-
891
- /**
892
- * Sets/unsets the pointer and marker in browse mode
893
- *
894
- * @param object the table row
895
- * @param integer the row number
896
- * @param string the action calling this script (over, out or click)
897
- * @param string the default background color
898
- * @param string the color to use for mouseover
899
- * @param string the color to use for marking a row
900
- *
901
- * @return boolean whether pointer is set or not
902
- */
903
- function setPointer(theRow, theRowNum, theAction, theDefaultColor, thePointerColor, theMarkColor)
904
- {
905
- var theCells = null;
906
-
907
- // 1. Pointer and mark feature are disabled or the browser can't get the
908
- // row -> exits
909
- if ((thePointerColor == '' && theMarkColor == '')
910
- || typeof(theRow.style) == 'undefined') {
911
- return false;
912
- }
913
-
914
- // 2. Gets the current row and exits if the browser can't get it
915
- if (typeof(document.getElementsByTagName) != 'undefined') {
916
- theCells = theRow.getElementsByTagName('td');
917
- }
918
- else if (typeof(theRow.cells) != 'undefined') {
919
- theCells = theRow.cells;
920
- }
921
- else {
922
- return false;
923
- }
924
-
925
- // 3. Gets the current color...
926
- var rowCellsCnt = theCells.length;
927
- var domDetect = null;
928
- var currentColor = null;
929
- var newColor = null;
930
- // 3.1 ... with DOM compatible browsers except Opera that does not return
931
- // valid values with "getAttribute"
932
- if (typeof(window.opera) == 'undefined'
933
- && typeof(theCells[0].getAttribute) != 'undefined') {
934
- currentColor = theCells[0].getAttribute('bgcolor');
935
- domDetect = true;
936
- }
937
- // 3.2 ... with other browsers
938
- else {
939
- currentColor = theCells[0].style.backgroundColor;
940
- domDetect = false;
941
- } // end 3
942
-
943
- // 3.3 ... Opera changes colors set via HTML to rgb(r,g,b) format so fix it
944
- if (currentColor.indexOf("rgb") >= 0)
945
- {
946
- var rgbStr = currentColor.slice(currentColor.indexOf('(') + 1,
947
- currentColor.indexOf(')'));
948
- var rgbValues = rgbStr.split(",");
949
- currentColor = "#";
950
- var hexChars = "0123456789ABCDEF";
951
- for (var i = 0; i < 3; i++)
952
- {
953
- var v = rgbValues[i].valueOf();
954
- currentColor += hexChars.charAt(v/16) + hexChars.charAt(v%16);
955
- }
956
- }
957
-
958
- // 4. Defines the new color
959
- // 4.1 Current color is the default one
960
- if (currentColor == ''
961
- || currentColor.toLowerCase() == theDefaultColor.toLowerCase()) {
962
- if (theAction == 'over' && thePointerColor != '') {
963
- newColor = thePointerColor;
964
- }
965
- else if (theAction == 'click' && theMarkColor != '') {
966
- newColor = theMarkColor;
967
- marked_row[theRowNum] = true;
968
- // Garvin: deactivated onclick marking of the checkbox because it's also executed
969
- // when an action (like edit/delete) on a single item is performed. Then the checkbox
970
- // would get deactived, even though we need it activated. Maybe there is a way
971
- // to detect if the row was clicked, and not an item therein...
972
- // document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
973
- }
974
- }
975
- // 4.1.2 Current color is the pointer one
976
- else if (currentColor.toLowerCase() == thePointerColor.toLowerCase()
977
- && (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum])) {
978
- if (theAction == 'out') {
979
- newColor = theDefaultColor;
980
- }
981
- else if (theAction == 'click' && theMarkColor != '') {
982
- newColor = theMarkColor;
983
- marked_row[theRowNum] = true;
984
- // document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
985
- }
986
- }
987
- // 4.1.3 Current color is the marker one
988
- else if (currentColor.toLowerCase() == theMarkColor.toLowerCase()) {
989
- if (theAction == 'click') {
990
- newColor = (thePointerColor != '')
991
- ? thePointerColor
992
- : theDefaultColor;
993
- marked_row[theRowNum] = (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum])
994
- ? true
995
- : null;
996
- // document.getElementById('id_rows_to_delete' + theRowNum).checked = false;
997
- }
998
- } // end 4
999
-
1000
- // 5. Sets the new color...
1001
- if (newColor) {
1002
- var c = null;
1003
- // 5.1 ... with DOM compatible browsers except Opera
1004
- if (domDetect) {
1005
- for (c = 0; c < rowCellsCnt; c++) {
1006
- theCells[c].setAttribute('bgcolor', newColor, 0);
1007
- } // end for
1008
- }
1009
- // 5.2 ... with other browsers
1010
- else {
1011
- for (c = 0; c < rowCellsCnt; c++) {
1012
- theCells[c].style.backgroundColor = newColor;
1013
- }
1014
- }
1015
- } // end 5
1016
-
1017
- return true;
1018
- } // end of the 'setPointer()' function
1019
-
1020
-
1021
- /**
1022
- * getElement
1023
- */
1024
- function getElement(e,f){
1025
- if(document.layers){
1026
- f=(f)?f:self;
1027
- if(f.document.layers[e]) {
1028
- return f.document.layers[e];
1029
- }
1030
- for(W=0;i<f.document.layers.length;W++) {
1031
- return(getElement(e,fdocument.layers[W]));
1032
- }
1033
- }
1034
- if(document.all) {
1035
- return document.all[e];
1036
- }
1037
- return document.getElementById(e);
1038
- }
1039
- </script>
1040
- </head>
1041
- <body bgcolor="white">
1042
- <table cellspacing="4" width ="80%" align="center">
1043
- <tr>
1044
- <td colspan="3" align="left" class="normal_trace_entry">
1045
- <p class="data" style="font-size: large; margin: 0px; border-color: red;"><b>Exception raised!</b><br />
1046
- <b>%exception%</b>: <b>%message%</b><br />
1047
- Time: <b>%time%</b>
1048
- </p>
1049
- </td>
1050
- </tr>
1051
- <tr>
1052
- <td class="trace_header"><b>File</b></td>
1053
- <td class="trace_header"><b>Line</b></td>
1054
- <td class="trace_header"><b>Info</b></td>
1055
- </tr>
1056
- START:backtrace
1057
- IFNOT:from_stdlib
1058
- <tr bgcolor="white" onmouseover="setPointer(this, %iteration_id%, 'over', 'white', '#CCFFCC', '#FFB2B2');" onmouseout="setPointer(this, %iteration_id%, 'out', 'white', '#CCFFCC', '#FFB2B2');" onmousedown="toggleCode('src%iteration_id%'); setPointer(this, %iteration_id%, 'click', 'white', '#CCFFCC', '#FFB2B2');">
1059
- IF:text
1060
- <td bgcolor="white" class="normal_trace_entry">%file%</td>
1061
- <td bgcolor="white" class="normal_trace_entry">%line%</td>
1062
- <td bgcolor="white" class="normal_trace_entry">%text%</td>
1063
- ENDIF:text
1064
- IFNOT:text
1065
- <td bgcolor="white" class="normal_trace_entry">%file%</td>
1066
- <td bgcolor="white" class="normal_trace_entry" colspan="2">%line%</td>
1067
- ENDIF:text
1068
- IF:source
1069
- </tr>
1070
- <tr>
1071
- <td colspan="3"><div id="src%iteration_id%" class="source"><tt><pre>%source%</pre></tt></div></td>
1072
- ENDIF:source
1073
- ENDIF:from_stdlib
1074
- IF:from_stdlib
1075
- <tr bgcolor="white" onmouseover="setPointer(this, %iteration_id%, 'over', 'white', '#CCFFCC', '#FFB2B2');" onmouseout="setPointer(this, %iteration_id%, 'out', 'white', '#CCFFCC', '#FFB2B2');" onmousedown="setPointer(this, %iteration_id%, 'click', 'white', '#CCFFCC', '#FFB2B2');">
1076
- IF:text
1077
- <td bgcolor="white" class="stdlib_trace_entry">%file%</td>
1078
- <td bgcolor="white" class="stdlib_trace_entry">%line%</td>
1079
- <td bgcolor="white" class="stdlib_trace_entry">%text%</td>
1080
- ENDIF:text
1081
- IFNOT:text
1082
- <td bgcolor="white" class="stdlib_trace_entry">%file%</td>
1083
- <td bgcolor="white" class="stdlib_trace_entry" colspan="2">%line%</td>
1084
- ENDIF:text
1085
- ENDIF:from_stdlib
1086
- </tr>
1087
-
1088
- END:backtrace
1089
- </table>
1090
- </body>
1091
- </html>