ruby-vpi 16.0.1 → 17.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (247) hide show
  1. data/LICENSE +19 -19
  2. data/README +1 -1
  3. data/Rakefile +35 -32
  4. data/bin/convert.rb +28 -0
  5. data/bin/generate/design.rb +16 -0
  6. data/bin/generate/proto.rb +13 -0
  7. data/bin/generate/runner.rake +33 -0
  8. data/bin/generate/spec.rb +45 -0
  9. data/bin/generate.rb +177 -0
  10. data/bin/ruby-vpi +56 -0
  11. data/doc/Rakefile +20 -4
  12. data/doc/common.css +92 -33
  13. data/doc/common.inc +13 -0
  14. data/doc/common.tpl +42 -28
  15. data/doc/history.doc +11 -11
  16. data/doc/history.html +769 -248
  17. data/doc/history.inc +909 -0
  18. data/doc/history.rb +9 -0
  19. data/doc/history.yaml +69 -0
  20. data/doc/intro.inc +170 -178
  21. data/doc/lib/doc_format.rb +57 -144
  22. data/doc/lib/doc_proxy.rb +504 -88
  23. data/doc/lib/erb_content.rb +8 -8
  24. data/doc/lib/erb_proxy.rb +17 -17
  25. data/doc/manual.doc +626 -777
  26. data/doc/manual.html +1541 -1031
  27. data/doc/memo.doc +38 -36
  28. data/doc/memo.html +64 -28
  29. data/doc/readme.doc +4 -31
  30. data/doc/readme.html +221 -163
  31. data/doc/rss.erb +1 -1
  32. data/doc/rss.xml +73 -1761
  33. data/ext/Rakefile +6 -5
  34. data/ext/main.c +17 -15
  35. data/ext/relay.c +4 -7
  36. data/ext/relay.h +2 -2
  37. data/ext/swig_vpi.h +2 -2
  38. data/ext/swig_vpi.i +1 -2
  39. data/ext/swig_wrap.cin +12 -16
  40. data/ext/vlog.c +5 -5
  41. data/ext/vlog.h +2 -2
  42. data/lib/ruby-vpi/erb.rb +3 -3
  43. data/lib/ruby-vpi/float.rb +2 -2
  44. data/lib/ruby-vpi/rcov.rb +5 -7
  45. data/lib/ruby-vpi/runner.rb +43 -41
  46. data/lib/ruby-vpi/runner_boot_loader.rb +117 -0
  47. data/lib/ruby-vpi/runner_proxy.rb +6 -8
  48. data/lib/ruby-vpi/util.rb +10 -0
  49. data/lib/ruby-vpi/verilog_parser.rb +28 -56
  50. data/lib/ruby-vpi/vpi.rb +168 -123
  51. data/lib/ruby-vpi.rb +22 -143
  52. data/ref/c/annotated.html +1 -1
  53. data/ref/c/common_8h.html +1 -1
  54. data/ref/c/files.html +1 -1
  55. data/ref/c/functions.html +1 -1
  56. data/ref/c/functions_vars.html +1 -1
  57. data/ref/c/globals.html +1 -1
  58. data/ref/c/globals_0x63.html +1 -1
  59. data/ref/c/globals_0x65.html +1 -1
  60. data/ref/c/globals_0x66.html +1 -1
  61. data/ref/c/globals_0x6d.html +1 -1
  62. data/ref/c/globals_0x70.html +1 -1
  63. data/ref/c/globals_0x72.html +1 -1
  64. data/ref/c/globals_0x73.html +1 -1
  65. data/ref/c/globals_0x74.html +1 -1
  66. data/ref/c/globals_0x76.html +1 -1
  67. data/ref/c/globals_0x78.html +1 -1
  68. data/ref/c/globals_defs.html +1 -1
  69. data/ref/c/globals_defs_0x65.html +1 -1
  70. data/ref/c/globals_defs_0x70.html +1 -1
  71. data/ref/c/globals_defs_0x76.html +1 -1
  72. data/ref/c/globals_defs_0x78.html +1 -1
  73. data/ref/c/globals_enum.html +1 -1
  74. data/ref/c/globals_eval.html +1 -1
  75. data/ref/c/globals_func.html +1 -1
  76. data/ref/c/globals_type.html +1 -1
  77. data/ref/c/globals_vars.html +1 -1
  78. data/ref/c/index.html +1 -1
  79. data/ref/c/main_8c.html +1 -1
  80. data/ref/c/main_8h.html +1 -1
  81. data/ref/c/relay_8c.html +1 -1
  82. data/ref/c/relay_8h.html +1 -1
  83. data/ref/c/structt__cb__data.html +1 -1
  84. data/ref/c/structt__vpi__delay.html +1 -1
  85. data/ref/c/structt__vpi__error__info.html +1 -1
  86. data/ref/c/structt__vpi__strengthval.html +1 -1
  87. data/ref/c/structt__vpi__systf__data.html +1 -1
  88. data/ref/c/structt__vpi__time.html +1 -1
  89. data/ref/c/structt__vpi__value.html +1 -1
  90. data/ref/c/structt__vpi__vecval.html +1 -1
  91. data/ref/c/structt__vpi__vlog__info.html +1 -1
  92. data/ref/c/verilog_8h.html +1 -1
  93. data/ref/c/vlog_8c.html +1 -1
  94. data/ref/c/vlog_8h.html +1 -1
  95. data/ref/c/vpi__user_8h.html +1 -1
  96. data/ref/ruby/classes/ERB.html +5 -5
  97. data/ref/ruby/classes/ERB.src/{M000024.html → M000026.html} +0 -0
  98. data/ref/ruby/classes/FileUtils.html +11 -11
  99. data/ref/ruby/classes/FileUtils.src/{M000025.html → M000027.html} +0 -0
  100. data/ref/ruby/classes/FileUtils.src/{M000026.html → M000028.html} +0 -0
  101. data/ref/ruby/classes/Float.html +6 -6
  102. data/ref/ruby/classes/Float.src/{M000020.html → M000021.html} +0 -0
  103. data/ref/ruby/classes/Integer.html +65 -65
  104. data/ref/ruby/classes/Integer.src/M000009.html +12 -5
  105. data/ref/ruby/classes/Integer.src/M000010.html +5 -5
  106. data/ref/ruby/classes/Integer.src/M000011.html +5 -5
  107. data/ref/ruby/classes/Integer.src/M000012.html +5 -5
  108. data/ref/ruby/classes/Integer.src/M000013.html +5 -5
  109. data/ref/ruby/classes/Integer.src/M000014.html +18 -0
  110. data/ref/ruby/classes/Integer.src/M000017.html +12 -18
  111. data/ref/ruby/classes/Integer.src/M000018.html +18 -12
  112. data/ref/ruby/classes/Integer.src/M000019.html +12 -17
  113. data/ref/ruby/classes/Integer.src/M000020.html +30 -0
  114. data/ref/ruby/classes/RDoc.html +5 -5
  115. data/ref/ruby/classes/RDoc.src/{M000053.html → M000058.html} +0 -0
  116. data/ref/ruby/classes/{RubyVpi/Config.html → RubyVPI.html} +20 -6
  117. data/ref/ruby/classes/String.html +34 -15
  118. data/ref/ruby/classes/String.src/M000022.html +5 -28
  119. data/ref/ruby/classes/String.src/M000023.html +5 -5
  120. data/ref/ruby/classes/String.src/{M000021.html → M000024.html} +0 -0
  121. data/ref/ruby/classes/String.src/M000025.html +41 -0
  122. data/ref/ruby/classes/VerilogParser/Module/Port.html +16 -36
  123. data/ref/ruby/classes/VerilogParser/Module/Port.src/M000006.html +10 -5
  124. data/ref/ruby/classes/VerilogParser/Module/Port.src/{M000004.html → M000007.html} +4 -4
  125. data/ref/ruby/classes/VerilogParser/Module/Port.src/{M000005.html → M000008.html} +4 -4
  126. data/ref/ruby/classes/VerilogParser/Module.html +28 -9
  127. data/ref/ruby/classes/VerilogParser/Module.src/M000005.html +29 -0
  128. data/ref/ruby/classes/VerilogParser.html +5 -39
  129. data/ref/ruby/classes/VerilogParser.src/M000004.html +26 -0
  130. data/ref/ruby/classes/Vpi/Handle.html +179 -77
  131. data/ref/ruby/classes/Vpi/Handle.src/M000035.html +18 -0
  132. data/ref/ruby/classes/Vpi/Handle.src/M000036.html +5 -5
  133. data/ref/ruby/classes/Vpi/Handle.src/M000037.html +5 -5
  134. data/ref/ruby/classes/Vpi/Handle.src/M000038.html +5 -5
  135. data/ref/ruby/classes/Vpi/Handle.src/M000039.html +5 -5
  136. data/ref/ruby/classes/Vpi/Handle.src/M000040.html +5 -8
  137. data/ref/ruby/classes/Vpi/Handle.src/M000041.html +5 -8
  138. data/ref/ruby/classes/Vpi/Handle.src/M000042.html +5 -9
  139. data/ref/ruby/classes/Vpi/Handle.src/M000043.html +8 -31
  140. data/ref/ruby/classes/Vpi/Handle.src/M000044.html +8 -74
  141. data/ref/ruby/classes/Vpi/Handle.src/M000045.html +9 -17
  142. data/ref/ruby/classes/Vpi/Handle.src/M000046.html +31 -11
  143. data/ref/ruby/classes/Vpi/Handle.src/M000047.html +86 -0
  144. data/ref/ruby/classes/Vpi/Handle.src/M000048.html +17 -18
  145. data/ref/ruby/classes/Vpi/Handle.src/M000050.html +18 -0
  146. data/ref/ruby/classes/Vpi/Handle.src/M000051.html +24 -0
  147. data/ref/ruby/classes/Vpi/Handle.src/M000053.html +31 -0
  148. data/ref/ruby/classes/Vpi/Handle.src/M000054.html +89 -0
  149. data/ref/ruby/classes/Vpi/S_vpi_time.html +16 -16
  150. data/ref/ruby/classes/Vpi/S_vpi_time.src/{M000050.html → M000055.html} +4 -4
  151. data/ref/ruby/classes/Vpi/S_vpi_time.src/{M000051.html → M000056.html} +5 -5
  152. data/ref/ruby/classes/Vpi/S_vpi_value.html +15 -15
  153. data/ref/ruby/classes/Vpi/S_vpi_value.src/{M000035.html → M000032.html} +5 -5
  154. data/ref/ruby/classes/Vpi/S_vpi_value.src/M000033.html +5 -5
  155. data/ref/ruby/classes/Vpi/S_vpi_value.src/M000034.html +5 -5
  156. data/ref/ruby/classes/Vpi.html +6 -42
  157. data/ref/ruby/classes/Vpi.src/M000029.html +15 -5
  158. data/ref/ruby/classes/Vpi.src/M000030.html +24 -24
  159. data/ref/ruby/classes/Vpi.src/M000031.html +6 -8
  160. data/ref/ruby/created.rid +1 -1
  161. data/ref/ruby/files/bin/{header_to_ruby_rb.html → convert_rb.html} +5 -5
  162. data/ref/ruby/files/bin/{generate_test_rb.html → generate_rb.html} +8 -21
  163. data/ref/ruby/files/lib/ruby-vpi/erb_rb.html +1 -1
  164. data/ref/ruby/files/lib/ruby-vpi/float_rb.html +1 -1
  165. data/ref/ruby/files/lib/ruby-vpi/integer_rb.html +1 -1
  166. data/ref/ruby/files/lib/ruby-vpi/rake_rb.html +1 -1
  167. data/ref/ruby/files/lib/ruby-vpi/rcov_rb.html +1 -1
  168. data/ref/ruby/files/lib/ruby-vpi/rdoc_rb.html +1 -1
  169. data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.html +197 -0
  170. data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.src/M000001.html +17 -0
  171. data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.src/M000002.html +18 -0
  172. data/ref/ruby/files/lib/ruby-vpi/runner_proxy_rb.html +1 -1
  173. data/ref/ruby/files/lib/ruby-vpi/runner_rb.html +6 -19
  174. data/ref/ruby/files/lib/ruby-vpi/util_rb.html +101 -0
  175. data/ref/ruby/files/lib/ruby-vpi/verilog_parser_rb.html +8 -1
  176. data/ref/ruby/files/lib/ruby-vpi/vpi_rb.html +1 -1
  177. data/ref/ruby/files/lib/ruby-vpi_rb.html +2 -14
  178. data/ref/ruby/fr_class_index.html +1 -3
  179. data/ref/ruby/fr_file_index.html +4 -2
  180. data/ref/ruby/fr_method_index.html +56 -51
  181. data/ref/ruby/index.html +1 -1
  182. data/samp/counter/RSpec/Rakefile +1 -0
  183. data/samp/counter/RSpec/counter_design.rb +15 -0
  184. data/samp/counter/RSpec/counter_proto.rb +10 -0
  185. data/samp/counter/RSpec/counter_runner.rake +44 -0
  186. data/samp/counter/RSpec/counter_spec.rb +39 -0
  187. data/samp/counter/Rakefile +1 -1
  188. data/samp/counter/counter.v +7 -7
  189. data/samp/counter/xUnit/Rakefile +1 -0
  190. data/samp/counter/xUnit/counter_bench.rb +95 -0
  191. data/samp/counter/{counter_xunit_bench.v → xUnit/counter_bench.v} +0 -0
  192. data/samp/counter/xUnit/counter_design.rb +15 -0
  193. data/samp/counter/xUnit/counter_proto.rb +10 -0
  194. data/samp/counter/xUnit/counter_runner.rake +44 -0
  195. data/samp/counter/{counter_xunit_spec.rb → xUnit/counter_spec.rb} +9 -9
  196. data/samp/pipelined_alu/Rakefile +1 -1
  197. data/samp/pipelined_alu/TestHw5UnitModel.rb +4 -5
  198. data/samp/pipelined_alu/hw5_unit.v +55 -85
  199. data/samp/pipelined_alu/hw5_unit_design.rb +51 -0
  200. data/samp/pipelined_alu/hw5_unit_proto.rb +4 -0
  201. data/samp/pipelined_alu/hw5_unit_runner.rake +43 -0
  202. data/samp/pipelined_alu/hw5_unit_spec.rb +64 -0
  203. data/samp/register_file/LICENSE +20 -0
  204. data/samp/register_file/README +4 -0
  205. data/samp/register_file/Rakefile +1 -0
  206. data/samp/register_file/register_file.v +18 -0
  207. data/samp/register_file/register_file_design.rb +11 -0
  208. data/samp/register_file/register_file_proto.rb +11 -0
  209. data/samp/register_file/register_file_runner.rake +43 -0
  210. data/samp/register_file/register_file_spec.rb +58 -0
  211. metadata +78 -66
  212. data/bin/generate_test.rb +0 -200
  213. data/bin/generate_test_tpl/bench.rb +0 -89
  214. data/bin/generate_test_tpl/bench.v +0 -26
  215. data/bin/generate_test_tpl/design.rb +0 -11
  216. data/bin/generate_test_tpl/proto.rb +0 -16
  217. data/bin/generate_test_tpl/runner.rake +0 -42
  218. data/bin/generate_test_tpl/spec.rb +0 -37
  219. data/bin/header_to_ruby.rb +0 -27
  220. data/ref/ruby/classes/Integer.src/M000008.html +0 -25
  221. data/ref/ruby/classes/Integer.src/M000016.html +0 -25
  222. data/ref/ruby/classes/RubyVpi.html +0 -199
  223. data/ref/ruby/classes/RubyVpi.src/M000027.html +0 -121
  224. data/ref/ruby/classes/VerilogParser/Module/Parameter.html +0 -160
  225. data/ref/ruby/classes/VerilogParser/Module/Parameter.src/M000007.html +0 -19
  226. data/ref/ruby/classes/VerilogParser/Module/Port.src/M000003.html +0 -21
  227. data/ref/ruby/classes/VerilogParser/Module.src/M000002.html +0 -34
  228. data/ref/ruby/classes/VerilogParser.src/M000001.html +0 -34
  229. data/ref/ruby/classes/Vpi/Handle.src/M000049.html +0 -69
  230. data/ref/ruby/classes/Vpi.src/M000028.html +0 -28
  231. data/ref/ruby/classes/Vpi.src/M000032.html +0 -22
  232. data/samp/counter/counter_rspec_bench.rb +0 -86
  233. data/samp/counter/counter_rspec_bench.v +0 -9
  234. data/samp/counter/counter_rspec_design.rb +0 -8
  235. data/samp/counter/counter_rspec_proto.rb +0 -13
  236. data/samp/counter/counter_rspec_runner.rake +0 -52
  237. data/samp/counter/counter_rspec_spec.rb +0 -39
  238. data/samp/counter/counter_xunit_bench.rb +0 -86
  239. data/samp/counter/counter_xunit_design.rb +0 -8
  240. data/samp/counter/counter_xunit_proto.rb +0 -13
  241. data/samp/counter/counter_xunit_runner.rake +0 -52
  242. data/samp/pipelined_alu/hw5_unit_test_bench.rb +0 -86
  243. data/samp/pipelined_alu/hw5_unit_test_bench.v +0 -14
  244. data/samp/pipelined_alu/hw5_unit_test_design.rb +0 -61
  245. data/samp/pipelined_alu/hw5_unit_test_proto.rb +0 -7
  246. data/samp/pipelined_alu/hw5_unit_test_runner.rake +0 -52
  247. data/samp/pipelined_alu/hw5_unit_test_spec.rb +0 -68
data/doc/lib/doc_proxy.rb CHANGED
@@ -2,145 +2,561 @@
2
2
  # Copyright 2006 Suraj N. Kurapati
3
3
  # See the file named LICENSE for details.
4
4
 
5
+ $: << File.basename(__FILE__)
5
6
  require 'erb_proxy'
6
7
  require 'doc_format'
7
8
 
8
- # Processes ERB templates to produce documentation. Templates may contain
9
- # "<xref...>" tags where the ... represents the target anchor of the
10
- # cross-reference.
9
+ require 'digest/md5'
10
+ require 'ostruct'
11
+ require 'pp'
12
+
13
+ class String
14
+ def digest
15
+ Digest::MD5.hexdigest self
16
+ end
17
+ end
18
+
19
+ # Processes ERB templates to produce documentation.
20
+ # Templates may contain "<xref...>" tags where the ...
21
+ # represents the target anchor of the cross-reference.
11
22
  class DocProxy < ErbProxy
12
- Block = Struct.new :anchor, :title, :type
13
- Heading = Struct.new :anchor, :title, :depth, :index
14
- Index = Struct.new :name, :items
23
+ Box = Struct.new(:type, :anchor, :index, :title, :id)
24
+ BibItem = Struct.new(:anchor, :name)
25
+ FootNote = Struct.new(:anchor, :name)
15
26
 
16
- CATEGORIES = {
27
+ GROUP2TYPES = {
17
28
  :admonition => [:tip, :note, :important, :caution, :warning],
18
29
 
19
- # formal blocks; see http://www.sagehill.net/docbookxsl/FormalTitles.html
30
+ # see http://www.sagehill.net/docbookxsl/FormalTitles.html
20
31
  :formal => [:figure, :table, :example, :equation, :procedure],
32
+
33
+ :latex => [:part, :chapter, :section, :paragraph],
21
34
  }
22
35
 
23
- attr_reader :blocks, :headings, :references
36
+ attr_reader :nodeTree, :references
24
37
 
25
38
  def initialize
26
39
  super
27
40
 
28
- @blocks = Hash.new {|h,k| h[k] = []}
29
- @headings = []
30
- @indexes = Hash.new {|h,k| h[k] = []}
41
+ @boxCipher = Cipher.new
42
+ @references = []
43
+ @boxes = Hash.new {|h,k| h[k] = []}
44
+ @lazyHandlers = {}
31
45
 
32
- CATEGORIES[:admonition].each do |type|
33
- add_block_handler :admonition, type do |index, title, text|
34
- join_redcloth_elements [
35
- %{!<images/tango/#{type}.png(#{type})!},
36
- %{p(title). #{type.to_s.capitalize}: #{title}},
37
- text,
38
- ]
46
+
47
+ # node hierarcy
48
+
49
+ @nodeTree = NodeTree.new
50
+
51
+ GROUP2TYPES.each_pair do |group, types|
52
+ next if group == :latex
53
+
54
+ types.each do |type|
55
+ add_node_handler group, type do |node, content, *args|
56
+ %{
57
+ <hr style="display: none"/>
58
+
59
+ <div class="#{group}">
60
+ <div class="#{type}" id="#{node.anchor}">
61
+ #{
62
+ if group == :admonition
63
+ %{<img src="images/tango/#{type}.png" alt="#{type}" class="icon"/>}
64
+ end
65
+ }
66
+
67
+ <p class="title"><a href="##{node.tocAnchor}">#{type.to_s.capitalize} #{node.number}</a>. &nbsp; #{node.title.to_html}</p>
68
+
69
+ #{content.to_html}
70
+ </div>
71
+ </div>
72
+ }
73
+ end
39
74
  end
40
75
  end
41
76
 
42
- CATEGORIES[:formal].each do |type|
43
- add_block_handler :formal, type do |index, title, text|
44
- join_redcloth_elements [
45
- %{p(title). #{type.to_s.capitalize} #{index}. #{title}},
46
- text,
77
+ add_node_handler :latex, :front_cover do |node, content, *args|
78
+ %{
79
+ <hr style="display: none"/>
80
+
81
+ <div id="#{node.anchor}" class="front_cover">
82
+ <h1 class="title"><big>#{node.title.to_html}</big></h1>
83
+
84
+ #{content.to_html}
85
+
86
+ </div>
87
+ }
88
+ end
89
+
90
+ add_node_handler :latex, :part do |node, content, *args|
91
+ %{
92
+ <hr style="display: none"/>
93
+
94
+ <div id="#{node.anchor}" class="part">
95
+ <h1 class="title">
96
+ Part <a href="##{node.tocAnchor}">#{node.number}</a>
97
+
98
+ <br/><br/>
99
+
100
+ <big>#{node.title.to_html}</big>
101
+ </h1>
102
+
103
+ #{content.to_html}
104
+
105
+ </div>
106
+ }
107
+ end
108
+
109
+ add_node_handler :latex, :chapter do |node, content, *args|
110
+ %{
111
+ <hr style="display: none"/>
112
+
113
+ <div id="#{node.anchor}" class="chapter">
114
+ <h1 class="title">
115
+ Chapter <a href="##{node.tocAnchor}">#{node.latexNumber}</a>
116
+
117
+ <br/><br/>
118
+
119
+ <big>#{node.title}</big>
120
+ </h1>
121
+
122
+ #{content.to_html}
123
+ </div>
124
+ }
125
+ end
126
+
127
+ add_node_handler :latex, :section do |node, content, *args|
128
+ level = [node.depth, 6].min
129
+
130
+ %{
131
+ <hr style="display: none"/>
132
+
133
+ <div id="#{node.anchor}" class="section">
134
+ <h#{level} class="title">
135
+ <a href="##{node.tocAnchor}">#{node.latexNumber}</a>
136
+
137
+ &nbsp;
138
+
139
+ #{node.title.to_html}
140
+ </h#{level}>
141
+
142
+ #{content.to_html}
143
+
144
+ </div>
145
+ }
146
+ end
147
+
148
+ add_node_handler :latex, :paragraph do |node, content, *args|
149
+ %{
150
+ <div id="#{node.anchor}" class="paragraph">
151
+ <p class="title">#{node.title.to_html}</p>
152
+ #{content.to_html}
153
+ </div>
154
+ }
155
+ end
156
+
157
+
158
+ @bibCipher = Cipher.new
159
+
160
+ # bibliography items
161
+ add_node_handler :index, :reference do |node, content, *args|
162
+ %{
163
+ <div id="#{node.anchor}" class="reference">
164
+ <table>
165
+ <tr>
166
+ <th>[#{node.number}]</th>
167
+ <td>#{content.to_html}</td>
168
+ </tr>
169
+ </table>
170
+ </div>
171
+ }
172
+ end
173
+
174
+ # bibliography items
175
+ add_handler :footnote do |caller, buffer, content, name|
176
+ anchor = "ref:#{name}".to_html_anchor
177
+ index = @footnotes.length
178
+ @footnotes << FootNote.new(anchor, name)
179
+
180
+ buffer << @bibCipher.encrypt(
181
+ [
182
+ %{<div id="#{anchor}">},
183
+ %{|_. [#{index}]|#{content}|}.to_html,
184
+ '</div>',
185
+ ].join
186
+ )
187
+ end
188
+
189
+ # bibliography citations
190
+ add_lazy_handler :cite do |target, *args|
191
+ node = @nodeTree.type2nodes[:reference].find {|n| n.id == target}
192
+
193
+ if node
194
+ words = [
195
+ %{<a href="##{node.anchor}">Reference #{node.number}</a>},
196
+
197
+ # extra information about the citation (page #, etc.)
198
+ *args.map {|s| s.to_html}
47
199
  ]
200
+
201
+ "(see #{ words.join(', ') })"
202
+ else
203
+ warn "invalid cite to #{target.inspect}"
204
+ ''
205
+ end
206
+ end
207
+
208
+ # cross references
209
+ add_lazy_handler :xref do |aTarget, aTitle|
210
+ nodes = @nodeTree.nodes
211
+ target = nodes.find {|n| n.id == aTarget} || # id has first priority
212
+ nodes.find {|n| n.anchor == aTarget}
213
+
214
+ if target
215
+ title = aTitle || "#{target.type.to_s.capitalize} #{target.latexNumber || target.number}"
216
+ %{<a href="##{target.anchor}">#{title.to_html}</a>}
217
+ else
218
+ warn "invalid xref to #{aTarget.inspect}"
219
+ ''
220
+ end
221
+ end
222
+ end
223
+
224
+ def add_lazy_handler aHandlerName, &aHandler
225
+ (class << self; self; end).instance_eval do
226
+ define_method aHandlerName do |*args|
227
+ token = "#{aHandlerName}#{args.object_id}".digest
228
+ @lazyHandlers[token] = [aHandler, args]
229
+ token
230
+ end
231
+ end
232
+ end
233
+
234
+ # aNodeType:: name of the command that will trigger the handler
235
+ # aNodeHandler:: handler that will be triggered by the given command
236
+ def add_node_handler aNodeGroup, aNodeType, &aNodeHandler #:yields: node, content, *args
237
+ raise ArgumentError unless block_given?
238
+
239
+ if @nodeTree.handlers.key? aNodeType
240
+ raise "node handler #{aNodeType.inspect} already exists"
241
+ end
242
+ @nodeTree.handlers[aNodeType] = aNodeHandler
243
+
244
+
245
+ add_handler aNodeType do |caller, buffer, content, nodeInfo, *args|
246
+ if @nodeTree.caller2node.key? caller
247
+ node = @nodeTree.caller2node[caller]
248
+
249
+ # collect tree traversal information
250
+ node.timesSeen += 1
251
+
252
+ else # first time we are handling this node
253
+
254
+ # parse the arguments given to this handler
255
+ if nodeInfo.respond_to? :to_hash
256
+ nodeInfo = nodeInfo.to_hash
257
+ raise ArgumentError unless nodeInfo.key? :title
258
+ else
259
+ nodeInfo = {:title => nodeInfo.to_s, :id => args.shift}
260
+ end
261
+
262
+ # register this node as having been seen
263
+ node = Node.new nodeInfo.merge(
264
+ # node info
265
+ :caller => caller,
266
+ :type => aNodeType,
267
+ :group => aNodeGroup,
268
+ :args => args,
269
+
270
+ # content info
271
+ :content => content,
272
+ :digest => content.digest,
273
+ :leadingSpace => (buffer =~ /([ \t]*)\Z/ && $1),
274
+
275
+ # traversal info
276
+ :orderSeen => @nodeTree.caller2node.keys.length,
277
+ :timesSeen => 1
278
+ )
279
+ @nodeTree.caller2node[caller] = node
48
280
  end
281
+
282
+ buffer << node.digest
49
283
  end
50
284
  end
51
285
 
52
286
  # Post-processes the given ERB template result by parsing the document
53
287
  # structure and expanding cross-references, and returns the result.
54
288
  def post_process aResult
55
- text = aResult.to_html
56
- anchors = []
289
+ text = aResult
57
290
 
58
- # parse document structure and insert anchors (so that the table of contents
59
- # can link directly to these headings) where necessary
60
- toc, text = text.table_of_contents do |title, anchor, index, depth, atts|
61
- @headings << Heading.new(anchor, title, depth, index)
62
- @blocks[:section] << Block.new(anchor, title, :section)
63
- end
291
+
292
+ # build the node tree
293
+ @nodeTree.build!
294
+ toc = @nodeTree.table_of_contents
295
+
296
+
297
+ # convert to HTML
298
+ File.open('text', 'w') {|f| f << text} if $DEBUG
299
+ html = text.to_html
300
+ File.open('html', 'w') {|f| f << html} if $DEBUG
301
+
302
+
303
+ @nodeTree.process_input! html, @innerSpace
64
304
 
65
305
  # expand cross-references into links to their targets
66
- blocks = @blocks.values.flatten
306
+ @lazyHandlers.each_pair do |token, (handler, args)|
307
+ html.gsub! token, handler.call(*args)
308
+ end
67
309
 
68
- text.gsub! %r{<xref\s*(.+?)\s*/?>} do
69
- anchor = unanchor($1)
70
- target = blocks.find {|b| b.anchor == anchor}
310
+ # expand all citations
311
+ # html = @bibCipher.decrypt_all(html)
71
312
 
72
- if target
73
- %{<a href="##{target.anchor}">the #{target.type} named &ldquo;#{target.title}&rdquo;</a>}
74
- else
75
- warn "unresolved cross-reference to #{anchor}"
76
- %{"#{anchor}":##{anchor}}
313
+
314
+ [toc, html]
315
+ end
316
+
317
+
318
+ ##-----------------------------------------------------------------------
319
+ # user API
320
+
321
+ # Unindents the inner space by the given amount.
322
+ def unindent aInnerSpace
323
+ @innerSpace = aInnerSpace
324
+ end
325
+
326
+ #-----------------------------------------------------------------------
327
+
328
+ private
329
+
330
+ def expand_includes aFilePath
331
+ input = File.read(aFilePath)
332
+
333
+ input.gsub! %r{<doc_proxy_include *(.*?)>} do
334
+ expand_includes($1)
335
+ end
336
+
337
+ input
338
+ end
339
+
340
+ #-----------------------------------------------------------------------
341
+
342
+ class Node < OpenStruct
343
+ undef id
344
+ undef type
345
+ end
346
+
347
+ class Cipher < Hash
348
+ def encrypt aString
349
+ digest = aString.digest
350
+ self[digest] = aString
351
+ digest
352
+ end
353
+
354
+ def decrypt digest
355
+ self[digest]
356
+ end
357
+
358
+ # Iteratively decrypts all digest substrings within the given string.
359
+ def decrypt_all aString
360
+ temp = self.dup
361
+ str = aString.dup
362
+
363
+ until temp.empty?
364
+ cipher = temp.find do |(digest, original)|
365
+ str.gsub! digest, original
77
366
  end
367
+
368
+ raise unless cipher
369
+ temp.delete cipher[0]
78
370
  end
79
371
 
80
- # determine index listings
81
- DocProxy::CATEGORIES.each_pair do |cat, types|
82
- category = cat.to_s.capitalize << 's'
372
+ str
373
+ end
374
+ end
375
+
376
+ class NodeTree < Hash
377
+ attr_reader :caller2node, :group2nodes, :type2nodes, :cipher, :handlers
83
378
 
84
- types.each do |type|
85
- items = @blocks[type]
379
+ def initialize
380
+ @cipher = Cipher.new
381
+ @handlers = {}
382
+ @caller2node = {}
383
+ @type2nodes = Hash.new {|h,k| h[k] = []}
384
+ @group2nodes = Hash.new {|h,k| h[k] = []}
385
+ end
386
+
387
+ def nodes
388
+ @caller2node.values
389
+ end
86
390
 
87
- unless items.empty?
88
- name = type.to_s.capitalize << 's'
89
- @indexes[category] << Index.new(name, items)
391
+ # Evaluates the given string which contains node digests.
392
+ def process_input! aString, aInnerSpace = nil
393
+ list = nodes
394
+
395
+ # let handlers modify node content
396
+ list.each do |node|
397
+ src = node.content
398
+ dst = @handlers[node.type].call(node, src, *node.args)
399
+
400
+ if aInnerSpace
401
+ space = node.leadingSpace + aInnerSpace
402
+
403
+ # add leading space if not present. this will ensure that
404
+ # lines without any leading space are correctly unindented
405
+ dst.gsub! %r/^[ \t]*/ do
406
+ if $&.index(space) == 0
407
+ $&
408
+ else
409
+ space + $&
410
+ end
90
411
  end
412
+
413
+ # remove leading space
414
+ dst.gsub! %r/^#{space}/, ''
91
415
  end
416
+
417
+ # XXX: escape single backslashes because they
418
+ # are removed later on for some reason...
419
+ dst.gsub! %r/\\/, '\&\&'
420
+
421
+ node.content = dst
92
422
  end
93
423
 
94
- [toc, text]
95
- end
424
+ # replace all node digests with node content
425
+ until list.empty?
426
+ target = list.find do |node|
427
+ aString.gsub! node.digest, node.content
428
+ end
96
429
 
97
- # Adds a block handler for the given type of block and outputs the result in a
98
- # <div> whose CSS class is the given category. The arguments for the block
99
- # handler are:
100
- #
101
- # 1. number of the block
102
- #
103
- # 2. title of the block
104
- #
105
- # 3. content of the block
106
- #
107
- def add_block_handler aCategory, aType
108
- raise ArgumentError unless block_given?
430
+ raise unless target
431
+ list.delete target
432
+ end
433
+ end
434
+
435
+ # Builds this tree from traversal information.
436
+ def build!
437
+ # build the tree
438
+ self.clear
439
+ children = []
440
+ lastDepth = 0
441
+
442
+ nodes.sort_by {|n| n.orderSeen}.each do |node|
443
+ currDepth = node.timesSeen
109
444
 
110
- add_handler aType do |buf, text, title, anchor|
111
- index = @blocks[aType].length + 1
445
+ # register this node into adjacency list
446
+ self[node] = [] unless self.key? node
112
447
 
113
- unless anchor
114
- anchor = "#{aType}#{index}"
448
+ if lastDepth > currDepth
449
+ subnodes = children.select {|n| n.timesSeen > currDepth}
450
+ self[node].concat subnodes
451
+ children = children - subnodes
452
+ end
453
+
454
+ children << node
455
+ lastDepth = currDepth
115
456
  end
116
- anchor = unanchor(anchor)
117
457
 
118
- @blocks[aType] << Block.new(anchor, title, aType)
458
+ if $DEBUG
459
+ nodes.each do |node|
460
+ def node.inspect
461
+ title.inspect
462
+ end
463
+ end
464
+ pp self
465
+ end
119
466
 
120
467
 
121
- elts = [
122
- %{<div class="#{aCategory}">},
123
- %{<div class="#{aType}" id="#{anchor}">},
124
- yield(index, title, text),
125
- '</div>',
126
- '</div>',
127
- ]
468
+ # set depths of all nodes starting from root-level nodes
469
+ rootNodes = self.keys - self.values.flatten.uniq
470
+ rootNodes.sort_by {|n| n.orderSeen}.each do |node|
471
+ set_depth node, 1
472
+ end
473
+
128
474
 
129
- text = join_redcloth_elements(elts)
130
- buf << text
475
+ # fill information for later stages
476
+ idUsage = Hash.new {|h,k| h[k] = []}
477
+
478
+ nodes.each do |node|
479
+ node.id ||= node.title
480
+ idUsage[node.id] << node
481
+
482
+ # forward and reverse anchors from & back to TOC
483
+ node.anchor = node.id.to_html_anchor
484
+ node.tocAnchor = node.object_id.to_s.to_html_anchor
485
+ end
486
+
487
+ idUsage.select {|(k,v)| v.length > 1}.each do |id, nodes|
488
+ warn "#{nodes.length} nodes have the same identifier: #{id.inspect}"
489
+ end
131
490
  end
132
- end
133
491
 
134
- private
492
+ def table_of_contents
493
+ toc = '<ul>'
494
+ prevDepth = 0
495
+ prevIndex = ''
135
496
 
136
- # Joins the given elements by putting enough white-space between them so that
137
- # RedCloth knows they're different elements.
138
- def join_redcloth_elements *args
139
- args.join("\n\n\n") << "\n\n\n"
140
- end
497
+ @group2nodes[:latex].each do |node|
498
+ # generate a LaTeX-style index (section number) for the heading
499
+ depthDiff = (node.depth - prevDepth).abs
500
+
501
+ node.latexNumber =
502
+ if node.depth > prevDepth
503
+ toc << '<li><ul>' * depthDiff
504
+
505
+ s = prevIndex + ('.1' * depthDiff)
506
+ s.sub(/^\./, '')
141
507
 
142
- # Removes the # from a HTML anchor so that only its name is preserved.
143
- def unanchor aAnchor
144
- aAnchor.sub(/^#+/, '')
508
+ elsif node.depth < prevDepth
509
+ toc << '</ul></li>' * depthDiff
510
+
511
+ s = prevIndex.sub(/(\.\d+){#{depthDiff}}$/, '')
512
+ s.next
513
+
514
+ else
515
+ prevIndex.next
516
+ end
517
+
518
+ prevDepth = node.depth
519
+ prevIndex = node.latexNumber
520
+
521
+
522
+ # generate hyperlink for traveling from TOC to heading
523
+ toc << %{<li><span class="hide">#{node.latexNumber} </span><a id="#{node.tocAnchor}" href="##{node.anchor}">#{node.title.to_html}</a></li>}
524
+ end
525
+
526
+ if prevIndex.empty?
527
+ toc = nil # there were no headings
528
+ else
529
+ toc << '</ul></li>' * prevDepth
530
+ toc << '</ul>'
531
+
532
+ # collapse redundant list elements
533
+ while toc.gsub! %r{(<li>.*?)</li><li>(<ul>)}, '\1\2'
534
+ end
535
+
536
+ # collapse unnecessary levels
537
+ while toc.gsub! %r{(<ul>)<li><ul>(.*)</ul></li>(</ul>)}, '\1\2\3'
538
+ end
539
+ end
540
+
541
+ toc
542
+ end
543
+
544
+ private
545
+
546
+ # recursively sets the depth of the given
547
+ # node and performs linear node numbering
548
+ def set_depth aNode, aDepth
549
+ aNode.depth = aDepth
550
+
551
+ # set number for boxes (fig 1, fig 2, etc.)
552
+ ary = @type2nodes[aNode.type]
553
+ ary << aNode
554
+ aNode.number = ary.length
555
+ @group2nodes[aNode.group] << aNode
556
+
557
+ self[aNode].each do |child|
558
+ set_depth child, aDepth + 1
559
+ end
560
+ end
145
561
  end
146
562
  end
@@ -4,13 +4,13 @@
4
4
 
5
5
  require 'erb'
6
6
 
7
- # Returns an array containing the current ERB buffer and the content that the
8
- # given block will append to the buffer when it is invoked.
7
+ # Returns an array containing the current ERB buffer and the content
8
+ # that the given block will append to the buffer when it is invoked.
9
9
  #
10
10
  # == Example
11
- # Suppose your ERB template invoked a method with some arguments and some
12
- # content in a block. You can pass the block to this method to obtain the
13
- # content contained within the block.
11
+ # Suppose your ERB template invoked a method with some arguments
12
+ # and some content in a block. You can pass the block to this
13
+ # method to obtain the content contained within the block.
14
14
  #
15
15
  ## template = ERB.new <<-EOS
16
16
  ## <% wrap_xml "message" do %>
@@ -18,8 +18,8 @@ require 'erb'
18
18
  ## <% end %>
19
19
  ## EOS
20
20
  #
21
- # In this case, the ERB template invokes the _wrap_xml_ method to wrap some
22
- # content within a pair of XML tags.
21
+ # In this case, the ERB template invokes the _wrap_xml_
22
+ # method to wrap some content within a pair of XML tags.
23
23
  #
24
24
  ## def wrap_xml tag, &block
25
25
  ## buffer, content = ERB.buffer_and_content(&block)
@@ -49,7 +49,7 @@ def ERB.buffer_and_content
49
49
  content = buffer.slice! a..b
50
50
 
51
51
  # buffer
52
- buffer.slice!((-content.length)..-1)
52
+ buffer.slice! -content.length..-1
53
53
 
54
54
  [buffer, content]
55
55
  end