-
Notifications
You must be signed in to change notification settings - Fork 229
Expand file tree
/
Copy pathSwigWrapToRDoc.rb
More file actions
239 lines (191 loc) · 6.14 KB
/
SwigWrapToRDoc.rb
File metadata and controls
239 lines (191 loc) · 6.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# Then modifies SWIG wrappers so they can be parsed by rdoc
# and calls rdoc.
#
# Inputs:
# ARGV[0] - path to build dir
# ARGV[1] - path to swig generated file
# ARGV[2] - name of the module to be generated
rdocify_dir = ARGV[0] + "/rdoc/"
rdoc = ARGV[0] + "/Ruby-install/release/bin/rdoc"
require 'pathname'
require 'fileutils'
include FileUtils
# check that called from command line directly
if not ($0 == __FILE__)
puts "#{__FILE__} called from external script"
exit
end
# make sure parent doc folder is in place
Dir.mkdir(rdocify_dir) if not File.exists?(rdocify_dir)
wrapper_file = ARGV[1]
name = ARGV[2]
output_dir = "#{rdocify_dir}#{name}/"
Dir.mkdir(output_dir) if not File.exists?(output_dir)
# empty output dir
Dir.glob("#{output_dir}*").each {|d| rm_rf(d)}
# get string of wrapper file to modify
str = nil
File.open(Pathname.new(wrapper_file), 'r') do |file|
str = file.read
end
puts "Pre-processing wrapper file #{wrapper_file}."
# delete header
str = str.split("\/\* -------- TYPES TABLE \(END\) -------- \*\/")
str = str[1]
# replace SWIGINTERN with static
str.gsub!("SWIGINTERN VALUE","static VALUE")
# put static VALUE on same line as function name
str.gsub!(/static VALUE\n/,"static VALUE ")
# process by /* chunks
strArray = str.split("\/\*")
orphanDoc = []
rbDefineBlockInd = strArray.length
strArray.each_index {|i|
# process last part of file, which includes rb_define calls
if !strArray[i].index(/SWIGEXPORT void Init_/).nil? then
rbDefineBlockInd = i
# simplify rb_define_class_under statement for derived classes
strArray[i].gsub!(/rb_define_class_under\(([\w]+,[ "\w]+,)[^;]+/,'rb_define_class_under(\1 rb_cObject)')
# break out of loop
break
end
# process blocks that include rdoc comments, delete all others
if strArray[i].index(/Document-[\w]*: /).nil? then
strArray[i] = ''
else
# change derived class documentation
# get base class and delete from first line
inheritanceDocRegex = /Document-class: ([\w:]*) < ([\w:]*)/
ans = strArray[i].match(inheritanceDocRegex)
if !ans.nil? then
# is derived class
baseClassStr = ans[2]
strArray[i].sub!(inheritanceDocRegex,'Document-class: \1')
# add sentence about base class
strArray[i].sub!(/Proxy of ([ \S]+)/,'Proxy of \1. Derived from ' << baseClassStr << '.')
end
# break documentation away from rest
brokenBlock = strArray[i].split(/\*\//)
if brokenBlock.size() != 2
warn "After splitting on /*, and then */, expected an array of size 2, but got an array of size " +
brokenBlock.size().to_s + "."
end
if (brokenBlock[1].strip).empty?
# no associated code, mark as orphan
orphanDoc[orphanDoc.length] = i
end
# delete unnecessary code
keepers = '' # will fill with lines to keep
lookingFor = '' # master overloaded function name
brokenBlock[1].each_line {|ln|
# possible keeper lines
if !ln.match(/static VALUE/).nil? ||
!ln.match(/_wrap_/).nil? ||
!ln.match(/swig_class/).nil? then
ln.sub!(" {","") # get rid of hanging open brackets
if ln.match(/__SWIG_\d+/).nil? # not an overloaded function
if (lookingFor == '') || !ln.match(lookingFor).nil?
keepers << ln
end
else # is an overloaded function
ans = ln.match(/(_wrap_[\w]+)__SWIG_\d+/) # look for master function
lookingFor = ans[1]
end
end
}
brokenBlock[1] = keepers
strArray[i] = brokenBlock[0]
strArray[i] << "*/\n" << brokenBlock[1] << "\n"
end
}
san = strArray.size()
orphanDoc.each_index { |j|
i = orphanDoc[j]
# strArray[i] is orphan, look for matching function
lookingFor = ''
# getters
if !strArray[i].match(/Get value/).nil?
lookingFor = "_get("
end
# setters
if !strArray[i].match(/Set new value/).nil?
lookingFor = "_set("
end
# pair getters
if !strArray[i].match(/Return the first element/).nil?
lookingFor = "_get("
end
if !strArray[i].match(/Return the second element/).nil?
lookingFor = "_get("
end
if lookingFor.empty?
puts "Unable to determine partial function signature for orphan documentation block:"
puts strArray[i]
next
end
ans = strArray[i].match(/Document-method: (?:\w+::)+(\w+\.\w+)/)
if !ans.nil?
lookingFor = "_" + ans[1].sub(/\./,"_") + lookingFor
else
next
end
lookingFor = Regexp.escape(lookingFor)
lnForOrphan = ''
startInd = i+1
endInd = rbDefineBlockInd - 1
for k in startInd..endInd
# break documentation away from rest
brokenBlock = strArray[k].split(/\*\//)
if brokenBlock.length <= 1
next
end
first = true
keepers = ''
replace = false
brokenBlock[1].each_line { |ln|
if (replace == false) && !ln.match(lookingFor).nil?
lnForOrphan = ln
if first
break
else
# delete from strArray[k]
replace = true
next
end
end
if !ln.match(/\w/).nil?
keepers << ln
first = false
end
}
if replace
brokenBlock[1] = keepers
strArray[k] = brokenBlock[0]
strArray[k] << "*/\n" << brokenBlock[1] << "\n"
end
end
if !lnForOrphan.empty?
strArray[i].chomp! << lnForOrphan.strip! << "\n\n"
else
puts "Unable to locate function declaration for orphan code block. Was looking for: " + lookingFor + "." # + " Code block is: "
# puts strArray[i]
end
if strArray.size() != san
warn "strArray is no longer the same size after processing orphan block " + j.to_s + ", that is, strArray[" + i.to_s + "]"
end
}
str = ''
strArray.each {|subStr|
if subStr != '' then
str << "/*" << subStr
end
}
puts "Writing file #{output_dir}#{name}.cxx"
# write file
File.open("#{output_dir}#{name}.cxx","w") do |file|
file.write(str)
end
# call rdoc
Dir.chdir(output_dir)
puts "Calling #{rdoc} from #{output_dir}"
system(rdoc)