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
|