ruby-vpi 16.0.1 → 17.0.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 (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