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
|
#!/usr/bin/python
import sys
import os
import os.path
import optparse
import subprocess
DOC_ID = "*%*"
class TaggedSource(object):
def __init__(self, f):
self._f = f
def __iter__(self):
return self
def next(self):
for line in self._f:
line = line.strip()
if DOC_ID not in line[:4]: # is documentation line?
continue
line = line[4:].strip()
if not line:
continue
if line == '*%*/': # end of annotation
break
i = line.find('#')
if i >= 0:
line = line[:i] # strip comments, if any
line = line.strip() # to be sure we're naked ;)
if line:
return line
raise StopIteration
# common XML output ancestor
class TCModuleDoc(object):
def __init__(self, name, src, srcname=""):
self._name = name
if srcname:
self._srcname = srcname
else:
self._srcname = "unknown"
if src:
self.parse(src)
def to_xml(self):
# feel free to suggest something nicer.
res = "<!-- %s -->" %(self._srcname)
T = self._tree
if not T:
return res
res += "\n" + \
" <varlistentry>\n" + \
" <term>\n" + \
" <option>%s</option>\n" %(self._name) + \
" <emphasis>[%s]</emphasis>\n" %(",".join(T["MEDIA"])) + \
" </term>\n" + \
" <listitem>\n" + \
" <para>%s</para>\n" %(T["DESCRIPTION"])
if "BUILD_DEPENDS" in T:
res += \
" <para>At compile time, this module requires: %s</para>\n" %(T["BUILD_DEPENDS"])
if "DEPENDS" in T:
res += \
" <para>At run time, this module requires: %s</para>\n" %(T["DEPENDS"])
opttree = T["OPTION"]
if opttree:
res += "<para>This module accepts the following options:</para>\n"
for (n, t), d in opttree.items():
res += \
" <variablelist>\n" + \
" <varlistentry>\n" + \
" <term>\n" + \
" <literal>%s (%s)</literal>\n" %(n, t) + \
" </term>\n" + \
" <listitem>\n" + \
" <para>%s</para>\n" %(d) + \
" </listitem>\n" + \
" </varlistentry>\n" + \
" </variablelist>\n"
res += "" + \
" </listitem>\n" + \
" </varlistentry>"
return res
def to_text(self):
# the simplest thing that works.
return "\n".join("%s: %s" %(k, self._tree[k]) for k in sorted(self._tree) )
def parse(self, data):
raise NotImplementedError
## what about decorator pattern or something like that?
class TCModuleDocFromTaggedSource(TCModuleDoc):
text_secs = set(("DESCRIPTION", "BUILD-DEPENDS", "DEPENDS", "PROCESSING"))
list_secs = set(("MEDIA", "INPUT", "OUTPUT"))
opts_secs = set(("OPTION",))
def _explode(self, opt):
return opt.replace('*', " (preferred)")
def _parse_opts(self, line, data, tree, outsecs):
key, val = line, []
for line in data:
if line in outsecs:
break
val.append(line)
n, t = key.split()
tree[(n, t.strip('()'))] = " ".join(val)
def parse(self, src):
self._tree = {}
this = TCModuleDocFromTaggedSource
all_secs = this.text_secs|this.list_secs|this.opts_secs
cur_sec = "" # unspecified/unknown
for line in src:
if line in all_secs:
cur_sec = line
continue
if cur_sec in this.text_secs:
if cur_sec in self._tree:
self._tree[cur_sec] += " " + line
else:
self._tree[cur_sec] = line
if cur_sec in this.list_secs:
self._tree[cur_sec] = [ o.replace('*', " (preferred)")
for o in line.split(',') ]
if cur_sec in this.opts_secs:
if cur_sec not in self._tree:
self._tree[cur_sec] = {}
self._parse_opts(line, src, self._tree[cur_sec], all_secs)
def _main():
parser = optparse.OptionParser()
parser.add_option("-s", "--source", dest="use_source",
action="store_true", default=False,
help="analyse sources of the module")
parser.add_option("-b", "--binary", dest="use_binary",
action="store_true", default=False,
help="analyse module objects using tcmodinfo")
options, args = parser.parse_args()
if not options.use_source and not options.use_binary:
print "either source or binary analysis mode must be selected"
sys.exit(1)
if options.use_binary:
print "not yet supported!"
sys.exit()
if options.use_source:
Src = TaggedSource
print "<!-- begin module list -->"
for mod in args:
try:
modname = os.path.basename(mod)
pre, name = modname.split('_')
root, ext = os.path.splitext(name)
doc = TCModuleDocFromTaggedSource(root,
TaggedSource(open(mod)),
modname)
print doc.to_xml()
except IOError:
pass # XXX
print "<!-- end module list -->"
if __name__ == "__main__":
_main()
# eof
|