bitclust-core 0.5.0

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 (127) hide show
  1. data/ChangeLog +2907 -0
  2. data/Gemfile +7 -0
  3. data/README +21 -0
  4. data/Rakefile +20 -0
  5. data/bin/bitclust +14 -0
  6. data/bin/refe +36 -0
  7. data/bitclust-dev.gemspec +33 -0
  8. data/bitclust.gemspec +30 -0
  9. data/config.in +23 -0
  10. data/config.ru +48 -0
  11. data/config.ru.sample +31 -0
  12. data/data/bitclust/catalog/ja_JP.EUC-JP +78 -0
  13. data/data/bitclust/catalog/ja_JP.UTF-8 +78 -0
  14. data/data/bitclust/template.lillia/class +98 -0
  15. data/data/bitclust/template.lillia/class-index +28 -0
  16. data/data/bitclust/template.lillia/doc +48 -0
  17. data/data/bitclust/template.lillia/layout +19 -0
  18. data/data/bitclust/template.lillia/library +129 -0
  19. data/data/bitclust/template.lillia/library-index +32 -0
  20. data/data/bitclust/template.lillia/method +20 -0
  21. data/data/bitclust/template.lillia/rd_file +6 -0
  22. data/data/bitclust/template.offline/class +67 -0
  23. data/data/bitclust/template.offline/class-index +28 -0
  24. data/data/bitclust/template.offline/doc +13 -0
  25. data/data/bitclust/template.offline/function +22 -0
  26. data/data/bitclust/template.offline/function-index +24 -0
  27. data/data/bitclust/template.offline/layout +18 -0
  28. data/data/bitclust/template.offline/library +87 -0
  29. data/data/bitclust/template.offline/library-index +32 -0
  30. data/data/bitclust/template.offline/method +21 -0
  31. data/data/bitclust/template.offline/rd_file +6 -0
  32. data/data/bitclust/template/class +133 -0
  33. data/data/bitclust/template/class-index +30 -0
  34. data/data/bitclust/template/doc +14 -0
  35. data/data/bitclust/template/function +21 -0
  36. data/data/bitclust/template/function-index +25 -0
  37. data/data/bitclust/template/layout +19 -0
  38. data/data/bitclust/template/library +89 -0
  39. data/data/bitclust/template/library-index +35 -0
  40. data/data/bitclust/template/method +24 -0
  41. data/data/bitclust/template/opensearchdescription +10 -0
  42. data/data/bitclust/template/search +57 -0
  43. data/lib/bitclust.rb +9 -0
  44. data/lib/bitclust/app.rb +129 -0
  45. data/lib/bitclust/classentry.rb +425 -0
  46. data/lib/bitclust/compat.rb +39 -0
  47. data/lib/bitclust/completion.rb +531 -0
  48. data/lib/bitclust/crossrubyutils.rb +91 -0
  49. data/lib/bitclust/database.rb +181 -0
  50. data/lib/bitclust/docentry.rb +83 -0
  51. data/lib/bitclust/entry.rb +223 -0
  52. data/lib/bitclust/exception.rb +38 -0
  53. data/lib/bitclust/functiondatabase.rb +115 -0
  54. data/lib/bitclust/functionentry.rb +81 -0
  55. data/lib/bitclust/functionreferenceparser.rb +76 -0
  56. data/lib/bitclust/htmlutils.rb +80 -0
  57. data/lib/bitclust/interface.rb +87 -0
  58. data/lib/bitclust/libraryentry.rb +211 -0
  59. data/lib/bitclust/lineinput.rb +165 -0
  60. data/lib/bitclust/messagecatalog.rb +95 -0
  61. data/lib/bitclust/methoddatabase.rb +401 -0
  62. data/lib/bitclust/methodentry.rb +202 -0
  63. data/lib/bitclust/methodid.rb +209 -0
  64. data/lib/bitclust/methodsignature.rb +82 -0
  65. data/lib/bitclust/nameutils.rb +236 -0
  66. data/lib/bitclust/parseutils.rb +60 -0
  67. data/lib/bitclust/preprocessor.rb +273 -0
  68. data/lib/bitclust/rdcompiler.rb +507 -0
  69. data/lib/bitclust/refsdatabase.rb +66 -0
  70. data/lib/bitclust/requesthandler.rb +330 -0
  71. data/lib/bitclust/ridatabase.rb +349 -0
  72. data/lib/bitclust/rrdparser.rb +522 -0
  73. data/lib/bitclust/runner.rb +143 -0
  74. data/lib/bitclust/screen.rb +554 -0
  75. data/lib/bitclust/searcher.rb +518 -0
  76. data/lib/bitclust/server.rb +59 -0
  77. data/lib/bitclust/simplesearcher.rb +84 -0
  78. data/lib/bitclust/subcommand.rb +746 -0
  79. data/lib/bitclust/textutils.rb +51 -0
  80. data/lib/bitclust/version.rb +3 -0
  81. data/packer.rb +224 -0
  82. data/refe2.gemspec +29 -0
  83. data/server.exe +0 -0
  84. data/server.exy +159 -0
  85. data/server.rb +10 -0
  86. data/setup.rb +1596 -0
  87. data/standalone.rb +193 -0
  88. data/test/run_test.rb +15 -0
  89. data/test/test_bitclust.rb +81 -0
  90. data/test/test_entry.rb +39 -0
  91. data/test/test_functiondatabase.rb +55 -0
  92. data/test/test_libraryentry.rb +31 -0
  93. data/test/test_methoddatabase.rb +81 -0
  94. data/test/test_methodsignature.rb +14 -0
  95. data/test/test_nameutils.rb +324 -0
  96. data/test/test_preprocessor.rb +84 -0
  97. data/test/test_rdcompiler.rb +534 -0
  98. data/test/test_refsdatabase.rb +76 -0
  99. data/test/test_rrdparser.rb +26 -0
  100. data/test/test_runner.rb +102 -0
  101. data/test/test_simplesearcher.rb +48 -0
  102. data/theme/default/images/external.png +0 -0
  103. data/theme/default/rurema.png +0 -0
  104. data/theme/default/style.css +288 -0
  105. data/theme/default/test.css +254 -0
  106. data/theme/lillia/rurema.png +0 -0
  107. data/theme/lillia/style.css +331 -0
  108. data/theme/lillia/test.css +254 -0
  109. data/tools/bc-ancestors.rb +153 -0
  110. data/tools/bc-checkparams.rb +246 -0
  111. data/tools/bc-classes.rb +80 -0
  112. data/tools/bc-convert.rb +165 -0
  113. data/tools/bc-list.rb +63 -0
  114. data/tools/bc-methods.rb +171 -0
  115. data/tools/bc-preproc.rb +42 -0
  116. data/tools/bc-rdoc.rb +343 -0
  117. data/tools/bc-tochm.rb +301 -0
  118. data/tools/bc-tohtml.rb +125 -0
  119. data/tools/bc-tohtmlpackage.rb +241 -0
  120. data/tools/check-signature.rb +19 -0
  121. data/tools/forall-ruby.rb +20 -0
  122. data/tools/gencatalog.rb +69 -0
  123. data/tools/statrefm.rb +98 -0
  124. data/tools/stattodo.rb +150 -0
  125. data/tools/update-database.rb +146 -0
  126. data/view.cgi +6 -0
  127. metadata +222 -0
@@ -0,0 +1,522 @@
1
+ #
2
+ # bitclust/rrdparser.rb
3
+ #
4
+ # Copyright (c) 2006-2007 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the Ruby License.
8
+ #
9
+
10
+ require 'bitclust/compat'
11
+ require 'bitclust/preprocessor'
12
+ require 'bitclust/methodid'
13
+ require 'bitclust/lineinput'
14
+ require 'bitclust/parseutils'
15
+ require 'bitclust/nameutils'
16
+ require 'bitclust/exception'
17
+ require 'bitclust/methoddatabase'
18
+
19
+ module BitClust
20
+
21
+ class RRDParser
22
+
23
+ include NameUtils
24
+ include ParseUtils
25
+
26
+ def RRDParser.parse_stdlib_file(path, params = {"version" => "1.9.0"})
27
+ parser = new(MethodDatabase.dummy(params))
28
+ parser.parse_file(path, libname(path), params)
29
+ end
30
+
31
+ def RRDParser.parse(s, lib, params = {"version" => "1.9.0"})
32
+ parser = new(MethodDatabase.dummy(params))
33
+ if s.respond_to?(:to_io)
34
+ io = s.to_io
35
+ elsif s.respond_to?(:to_str)
36
+ s1 = s.to_str
37
+ require 'stringio'
38
+ io = StringIO.new(s1)
39
+ else
40
+ io = s
41
+ end
42
+ l = parser.parse(io, lib, params)
43
+ return l, parser.db
44
+ end
45
+
46
+ def RRDParser.split_doc(source)
47
+ if m = /^=(\[a:.*?\])?( +(.*)|([^=].*))\r?\n/.match(source)
48
+ title = $3 || $4
49
+ s = m.post_match
50
+ return title, s
51
+ end
52
+ return ["", source]
53
+ end
54
+
55
+ def RRDParser.libname(path)
56
+ case path
57
+ when %r<(\A|/)_builtin/>
58
+ '_builtin'
59
+ else
60
+ path.sub(%r<\A(.*/)?src/>, '').sub(/\.rd(\.off)?\z/, '')
61
+ end
62
+ end
63
+ private_class_method :libname
64
+
65
+ def initialize(db)
66
+ @db = db
67
+ end
68
+ attr_reader :db
69
+
70
+ def parse_file(path, libname, params = {})
71
+ fopen(path, 'r:UTF-8') {|f|
72
+ return parse(f, libname, params)
73
+ }
74
+ end
75
+
76
+ def parse(f, libname, params = {})
77
+ @context = Context.new(@db, libname)
78
+ f = LineInput.new(Preprocessor.wrap(f, params))
79
+ do_parse f
80
+ @context.library
81
+ end
82
+
83
+ private
84
+
85
+ def do_parse(f)
86
+ f.skip_blank_lines
87
+ f.while_match(/\Arequire\s/) do |line|
88
+ @context.require line.split[1]
89
+ end
90
+ f.skip_blank_lines
91
+ f.while_match(/\Asublibrary\s/) do |line|
92
+ @context.sublibrary line.split[1]
93
+ end
94
+ f.skip_blank_lines
95
+ @context.library.source = f.break(/\A==?[^=]|\A---/).join('').rstrip
96
+ read_classes f
97
+ if line = f.gets # error
98
+ case line
99
+ when /\A==[^=]/
100
+ parse_error "met level-2 header in library document; maybe you forgot level-1 header", line
101
+ when /\A---/
102
+ parse_error "met bare method entry in library document; maybe you forgot reopen/redefine level-1 header", line
103
+ else
104
+ parse_error "unexpected line in library document", line
105
+ end
106
+ end
107
+ end
108
+
109
+ def read_classes(f)
110
+ f.while_match(/\A=[^=]/) do |line|
111
+ type, name, superclass = *parse_level1_header(line)
112
+ case type
113
+ when 'class'
114
+ @context.define_class name, (superclass || 'Object')
115
+ read_class_body f
116
+ when 'module'
117
+ parse_error "superclass given for module", line if superclass
118
+ @context.define_module name
119
+ read_class_body f
120
+ when 'object'
121
+ if superclass
122
+ # FIXME
123
+ tty_warn "#{line.location}: singleton object class not implemented yet"
124
+ end
125
+ @context.define_object name
126
+ read_object_body f
127
+ when 'reopen'
128
+ @context.reopen_class name
129
+ read_reopen_body f
130
+ when 'redefine'
131
+ @context.redefine_class name
132
+ read_reopen_body f
133
+ else
134
+ parse_error "wrong level-1 header", line
135
+ end
136
+ end
137
+ end
138
+
139
+ def parse_level1_header(line)
140
+ m = /\A(\S+)\s*([^\s<]+)(?:\s*<\s*(\S+))?\z/.match(line.sub(/\A=/, '').strip)
141
+ unless m
142
+ parse_error "level-1 header syntax error", line
143
+ end
144
+ return m[1], isconst(m[2], line), isconst(m[3], line)
145
+ end
146
+
147
+ def isconst(name, line)
148
+ return nil unless name
149
+ unless /\A#{CLASS_PATH_RE}\z/o =~ name
150
+ raise ParseError, "#{line.location}: not a constant: #{name.inspect}"
151
+ end
152
+ name
153
+ end
154
+
155
+ def read_class_body(f)
156
+ f.skip_blank_lines
157
+ read_aliases f
158
+ f.skip_blank_lines
159
+ read_extends f
160
+ read_includes f
161
+ f.skip_blank_lines
162
+ @context.klass.source = f.break(/\A==?[^=]|\A---/).join('').rstrip
163
+ read_level2_blocks f
164
+ end
165
+
166
+ def read_reopen_body(f)
167
+ f.skip_blank_lines
168
+ read_extends f, true
169
+ read_includes f, true
170
+ f.skip_blank_lines
171
+ read_level2_blocks f
172
+ end
173
+
174
+ def read_object_body(f)
175
+ f.skip_blank_lines
176
+ read_aliases f
177
+ f.skip_blank_lines
178
+ read_extends f
179
+ f.skip_blank_lines
180
+ @context.klass.source = f.break(/\A=|\A---/).join('').rstrip
181
+ @context.visibility = :public
182
+ @context.type = :singleton_method
183
+ read_entries f
184
+ end
185
+
186
+ def read_aliases(f)
187
+ f.while_match(/\Aalias\s/) do |line|
188
+ @context.alias line.split[1]
189
+ end
190
+ end
191
+
192
+ def read_includes(f, reopen = false)
193
+ f.while_match(/\Ainclude\s/) do |line|
194
+ tty_warn "#{line.location}: dynamic include is not implemented yet" if reopen
195
+ @context.include line.split[1] unless reopen # FIXME
196
+ end
197
+ end
198
+
199
+ def read_extends(f, reopen = false)
200
+ f.while_match(/\Aextend\s/) do |line|
201
+ tty_warn "#{line.location}: dynamic extend is not implemented yet" if reopen
202
+ @context.extend line.split[1] unless reopen # FIXME
203
+ end
204
+ end
205
+
206
+ def tty_warn(msg)
207
+ $stderr.puts msg if $stderr.tty?
208
+ end
209
+
210
+ def read_level2_blocks(f)
211
+ read_entries f
212
+ f.skip_blank_lines
213
+ f.while_match(/\A==[^=]/) do |line|
214
+ case line.sub(/\A==/, '').strip
215
+ when /\A((?:public|private|protected)\s+)?(?:(class|singleton|instance)\s+)?methods?\z/i
216
+ @context.visibility = ($1 || 'public').downcase.intern
217
+ t = ($2 || 'instance').downcase.sub(/class/, 'singleton')
218
+ @context.type = "#{t}_method".intern
219
+ when /\AModule\s+Functions?\z/i
220
+ @context.module_function
221
+ when /\AConstants?\z/i
222
+ @context.constant
223
+ when /\ASpecial\s+Variables?\z/i
224
+ @context.special_variable
225
+ else
226
+ parse_error "unknown level-2 header", line
227
+ end
228
+ read_entries f
229
+ end
230
+ end
231
+
232
+ def read_entries(f)
233
+ concat_aliases(read_chunks(f)).each do |chunk|
234
+ @context.define_method chunk
235
+ end
236
+ end
237
+
238
+ def concat_aliases(chunks)
239
+ return [] if chunks.empty?
240
+ result = [chunks.shift]
241
+ chunks.each do |chunk|
242
+ if result.last.alias?(chunk)
243
+ result.last.unify chunk
244
+ else
245
+ result.push chunk
246
+ end
247
+ end
248
+ result
249
+ end
250
+
251
+ def read_chunks(f)
252
+ f.skip_blank_lines
253
+ result = []
254
+ f.while_match(/\A---/) do |line|
255
+ f.ungets line
256
+ result.push read_chunk(f)
257
+ end
258
+ result
259
+ end
260
+
261
+ def read_chunk(f)
262
+ header = f.span(/\A---/)
263
+ body = f.break(/\A(?:---|={1,2}[^=])/)
264
+ src = (header + body).join('')
265
+ src.location = header[0].location
266
+ sigs = header.map {|line| method_signature(line) }
267
+ mainsig = check_chunk_signatures(sigs, header[0])
268
+ names = sigs.map {|s| s.name }.uniq.sort
269
+ Chunk.new(mainsig, names, src)
270
+ end
271
+
272
+ def check_chunk_signatures(sigs, line)
273
+ cxt = @context.signature
274
+ if cxt and cxt.fully_qualified?
275
+ if bad = sigs.detect {|sig| not cxt.compatible?(sig) }
276
+ parse_error "signature crash: `#{cxt}' given by level-1/2 header but method entry has a signature `#{bad}'; remove level-1/2 header or modify method entry", line
277
+ end
278
+ cxt
279
+ else
280
+ sig = sigs[0]
281
+ unless sig.fully_qualified?
282
+ if not cxt
283
+ parse_error "missing class and type; give full signature for method entry", line
284
+ elsif not cxt.type
285
+ parse_error "missing type: write level-2 header", line
286
+ elsif not cxt.klass
287
+ raise "must not happen: type given but class not exist: context=#{cxt}, entry=#{sig}"
288
+ else
289
+ raise "must not happen: context=#{cxt}, entry=#{sig}"
290
+ end
291
+ end
292
+ if cxt
293
+ unless sig.compatible?(cxt)
294
+ parse_error "signature crash: #{cxt} given by level-1/2 but method entry has a signature #{sig}; remove level-1/2 header or modify method entry", line
295
+ end
296
+ end
297
+ unless sigs.all? {|s| sig.same_type?(s) }
298
+ parse_error "alias entries have different class/type", line
299
+ end
300
+ sig
301
+ end
302
+ end
303
+
304
+ SIGNATURE = /\A---\s*(?:(#{CLASS_PATH_RE})(#{TYPEMARK_RE}))?(#{METHOD_NAME_RE})/
305
+ GVAR = /\A---\s*(#{GVAR_RE})/
306
+
307
+ def method_signature(line)
308
+ case
309
+ when m = SIGNATURE.match(line)
310
+ Signature.new(*m.captures)
311
+ when m = GVAR.match(line)
312
+ Signature.new(nil, '$', m[1][1..-1])
313
+ else
314
+ parse_error "wrong method signature", line
315
+ end
316
+ end
317
+
318
+ class Context
319
+ include NameUtils
320
+
321
+ def initialize(db, libname)
322
+ @db = db
323
+ #@library = @db.open_library(libname)
324
+ @library = @db.open_library(libname, true) # FIXME: always reopen
325
+ @klass = nil
326
+ @type = nil
327
+ @visibility = nil
328
+ end
329
+
330
+ attr_reader :library
331
+ attr_reader :klass
332
+ attr_accessor :type
333
+ attr_accessor :visibility
334
+
335
+ def require(libname)
336
+ @library.require @db.get_library(libname)
337
+ end
338
+
339
+ def sublibrary(libname)
340
+ @library.sublibrary @db.get_library(libname)
341
+ end
342
+
343
+ def define_class(name, supername)
344
+ if @db.properties['version'] >= "1.9.0"
345
+ top = 'BasicObject'
346
+ else
347
+ top = 'Object'
348
+ end
349
+ superclass = (name == top ? nil : @db.get_class(supername))
350
+ register_class :class, name, superclass
351
+ end
352
+
353
+ def define_module(name)
354
+ register_class :module, name, nil
355
+ end
356
+
357
+ def define_object(name)
358
+ register_class :object, name, nil
359
+ end
360
+
361
+ def register_class(type, name, superclass)
362
+ @klass = @db.open_class(name) {|c|
363
+ c.type = type
364
+ c.superclass = superclass
365
+ c.library = @library
366
+ @library.add_class c
367
+ }
368
+ @kind = :defined
369
+ clear_scope
370
+ end
371
+ private :register_class
372
+
373
+ def clear_scope
374
+ @type = nil
375
+ @visibility = nil
376
+ end
377
+ private :clear_scope
378
+
379
+ def reopen_class(name)
380
+ @kind = :added
381
+ @klass = name ? @db.get_class(name) : nil
382
+ clear_scope
383
+ end
384
+
385
+ def redefine_class(name)
386
+ @kind = :redefined
387
+ @klass = name ? @db.get_class(name) : nil
388
+ clear_scope
389
+ end
390
+
391
+ def include(name)
392
+ @klass.include @db.get_class(name)
393
+ end
394
+
395
+ def extend(name)
396
+ @klass.extend @db.get_class(name)
397
+ end
398
+
399
+ # Add a alias +name+ to the alias list.
400
+ def alias(name)
401
+ @db.open_class(name) do |c|
402
+ c.type = @klass.type
403
+ c.library = @library
404
+ c.aliasof = @klass
405
+ c.source = "Alias of [[c:#{@klass.name}]]\n"
406
+ @library.add_class c
407
+ @klass.alias c
408
+ end
409
+ end
410
+
411
+ def module_function
412
+ @type = :module_function
413
+ end
414
+
415
+ def constant
416
+ @type = :constant
417
+ end
418
+
419
+ def special_variable
420
+ unless @klass and @klass.name == 'Kernel'
421
+ raise "must not happen: type=special_variable but class!=Kernel"
422
+ end
423
+ @type = :special_variable
424
+ end
425
+
426
+ def signature
427
+ return nil unless @klass
428
+ Signature.new(@klass.name, @type ? typename2mark(@type) : nil, nil)
429
+ end
430
+
431
+ def define_method(chunk)
432
+ id = method_id(chunk)
433
+ @db.open_method(id) {|m|
434
+ m.names = chunk.names.sort
435
+ m.kind = @kind
436
+ m.visibility = @visibility || :public
437
+ m.source = chunk.source
438
+ case @kind
439
+ when :added, :redefined
440
+ @library.add_method m
441
+ end
442
+ }
443
+ end
444
+
445
+ def method_id(chunk)
446
+ id = MethodID.new
447
+ id.library = @library
448
+ id.klass = chunk.signature.klass ? @db.get_class(chunk.signature.klass) : @klass
449
+ id.type = chunk.signature.typename || @type
450
+ id.name = chunk.names.sort.first
451
+ id
452
+ end
453
+ end
454
+
455
+ class Chunk
456
+ def initialize(signature, names, source)
457
+ @signature = signature
458
+ @names = names
459
+ @source = source
460
+ end
461
+
462
+ attr_reader :signature
463
+ attr_reader :names
464
+ attr_reader :source
465
+
466
+ def inspect
467
+ "\#<Chunk #{@signature.klass}#{@signature.type}#{@names.join(',')} #{@source.location}>"
468
+ end
469
+
470
+ def alias?(other)
471
+ @signature.compatible?(other.signature) and
472
+ not (@names & other.names).empty?
473
+ end
474
+
475
+ def unify(other)
476
+ @names |= other.names
477
+ @source << other.source
478
+ end
479
+ end
480
+
481
+ class Signature
482
+ include NameUtils
483
+
484
+ def initialize(c, t, m)
485
+ @klass = c # String
486
+ @type = t
487
+ @name = m
488
+ end
489
+
490
+ attr_reader :klass
491
+ attr_reader :type
492
+ attr_reader :name
493
+
494
+ def inspect
495
+ "\#<signature #{to_s()}>"
496
+ end
497
+
498
+ def to_s
499
+ "#{@klass || '_'}#{@type || ' _ '}#{@name}"
500
+ end
501
+
502
+ def typename
503
+ typemark2name(@type)
504
+ end
505
+
506
+ def same_type?(other)
507
+ @klass == other.klass and @type == other.type
508
+ end
509
+
510
+ def compatible?(other)
511
+ (not @klass or not other.klass or @klass == other.klass) and
512
+ (not @type or not other.type or @type == other.type)
513
+ end
514
+
515
+ def fully_qualified?
516
+ (@klass and @type) ? true : false
517
+ end
518
+ end
519
+
520
+ end
521
+
522
+ end