xml2texi.rb
5.25 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
#!/usr/local/bin/ruby -w
if ! ARGV[0]
print <<USAGE
Usage: xml2texi.rb xml-file
The texinfo for function documentation found in xml-file
is dumped to stdout.
USAGE
exit 0
end
$\ = "\n"
require "rexml/document"
include REXML
# Utility functions
def printPara(p)
if p.name != "para"
raise "printPara: " + p.name + " not a paragraph!\n"
end
p.each do |c|
if c.kind_of? Text
print c
else
if c.name == "parameterlist"
# print "!! skipping parameterlist"
else
print "\n!! Unknown element type: ", c.name, "\n"
end
end
end
print "\n"
print "\n"
end
# Open the document, compress whitespace.
doc = Document.new File.new(ARGV[0]), { :compress_whitespace => :all }
# <?xml version='1.0' encoding='ISO-8859-1' standalone='yes'?>
# <doxygen version="1.2.15-20020430">
# <compounddef id="smtp_8c" kind="file">
# -- ...
#print "doc.whitespace: ", doc.whitespace
#print "doc.version: ", doc.version
#print "doc.encoding: ", doc.encoding
#print "doc.standalone: ", doc.standalone?
# Input:
#
# <sectiondef kind="func">
# <memberdef kind="function" id="smtp_8c_1a7" virt="normal" prot="public" const="no" volatile="no">
# <type>int</type>
# <name>smtp_open</name>
# <param>
# <type>mailer_t</type>
# <defname>mailer</defname>
# </param>
# <param>
# <type>int</type>
# <defname>flags</defname>
# </param>
# <briefdescription>
# <para>Open an SMTP mailer. </para>
# </briefdescription>
# <detaileddescription>
# <para>An SMTP mailer must be opened before any messages can be sent. <parameterlist kind="param"><title>Parameters: </title><parametername>mailer</parametername><parameterdescription><para>the mailer created by smtp_create() </para>
# </parameterdescription><parametername>flags</parametername><parameterdescription><para>the mailer flags </para>
# </parameterdescription></parameterlist></para>
# </detaileddescription>
# <location file="/home/sam/p/gnu/mailutils/mailbox/smtp.c" line="223" bodystart="289" bodyend="434"/>
# </memberdef>
# - Why do I always get XML, even for undocumented functions and macros?
# - Why is # there no markup that I can use to determine that the function
# was undocumented?
# - Why sometimes declname, sometimes defname, in param?
# - why is the parameter list jammed into the last paragraph of the
# detailed description?
# - Why is there always a detailed description, even when there isn't?
# - Why the duplication beteen the beginning list of <param> (which is
# lacking the <parameterdescription>, and the <parameterlist>?
# - Why is parameterlist just an alternating list of names and descriptions,
# with no markup to bind a name to a description?
# Overall: this appears to be half visual markup, and half logical. If
# it was entirely visual, there would be the one-line summary of the
# documented functions, followed by the details.
# If it was entirely markup, then the
# parameter info wouldn't be split into two different locations.
# Output:
#
# @deftypefun int smtp_open (
# mailer_t @var{mailer},
# int @var{flags})
# Open an SMTP mailer.
# An SMTP mailer must be opened before any messages can be sent.
#
# Parameters:
# @itemize
# @item @code{mailer} - the mailer created by smtp_create()
# @item @code{flags} - the mailer flags
# @end itemize
# @end deftypefun
doc.elements.each("*/*/sectiondef[@kind='func']") { |e|
print "section: ", e.name, "/", e.attributes["kind"]
e.elements.each("memberdef") { |m|
# If there is no brief description, don't document this member.
next unless m.elements["briefdescription"].elements["para"]
$\ = ""
print "@deftypefun "
if m.elements["type"].text
print m.elements["type"].text, " "
else
print "int "
end
print m.elements["name"].text, " (\n "
first = true
m.elements.each("param") { |p|
if(first)
first = false
else
print ",\n "
end
p.elements["type"].each { |c|
if c.kind_of? Text
print c, " "
else
c.each { |c2|
if c2.kind_of? Text
print c2, " "
end
}
end
}
name = p.elements["declname"];
if ! name
name = p.elements["defname"];
end
if name
print "@var{", name.text, "}"
end
}
print ")\n"
print m.elements["briefdescription"].elements["para"].text
dd = m.elements["detaileddescription"]
if dd
print "\n"
dd.each do |dde|
if dde.kind_of? Text
# Top level Text is empty.
else
# We should have a string of "para" elements, the last of which
# has the parameter list.
printPara dde
end
end
print "Parameters:\n"
print "@itemize\n"
dd.elements.each("*/parameterlist/*") do |pl|
if pl.name == "title"
# ignore
elsif pl.name == "parametername"
print "@item @code{", pl.text, "}"
elsif pl.name == "parameterdescription"
if pl.elements["para"]
print " - ", pl.elements["para"].text, "\n"
end
end
end
print "@end itemize\n"
end
print "@end deftypefun\n"
print "\n"
}
}