MAGMA  1.2.0
MatrixAlgebraonGPUandMulticoreArchitectures
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
gendoc.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 #
3 # Sample usage:
4 #
5 # python tools/gendoc src/z*.cpp
6 #
7 # the visit "htmldoc/index.html"
8 #
9 
10 import sys
11 import os
12 import re
13 
14 def is_all_char(s, ch):
15  """
16  All characters in 's' are 'ch'.
17  """
18 
19  for c in s:
20  if c != ch:
21  return 0
22 
23  return 1
24 
25 def cleanup(txt):
26  return "\n".join(cleanup_lst(txt.split("\n")))
27 
28 def cleanup_lst(txtlst):
29  last_empty = 0
30  only_empty = 1
31  empty_line = 0
32  i = 0
33  first_full = len(txtlst)
34 
35  if len(txtlst) > 1:
36  min_indent = max(map(len, txtlst))
37  else:
38  min_indent = 0
39 
40  for line in txtlst:
41  if len(line.strip()) == 0: # empty line
42  if not empty_line:
43  last_empty = i
44  empty_line = 1
45  else:
46  if only_empty:
47  first_full = i
48  only_empty = 0
49  empty_line = 0
50 
51  if not empty_line:
52  min_indent = min(min_indent, len(line) - len(line.lstrip()))
53 
54  i += 1
55 
56  all_lines = list()
57 
58  i = 0
59  for line in txtlst:
60  if i >= first_full and i <= last_empty:
61  all_lines.append(line.rstrip()[min_indent:])
62  i += 1
63 
64  return all_lines
65 
66 def parse_args(argstr):
67  arglst = argstr.split(",")
68  newarglist = list()
69  for a in arglst:
70  a = a.strip()
71  name = re.match("(\w+)", a[::-1]).group() # match argument name from the end (I'm assuming the name ends each argument)
72  prefix = a[:-len(name)]
73  newarglist.append((prefix, name[::-1]))
74 
75  return newarglist
76 
77 class FuncDoc:
78  def __init__(self, funcname, C_args, argdict, purpose, details):
79  self.funcname = funcname
80  self.C_args = C_args
81  self.argdict = argdict
82  self.purpose = purpose
83  self.details = details
84 
85 def getdoc(fname):
86  txt = open(fname).read()
87  purpose_idx = txt.find("\n", txt.find("Purpose")+14)+1
88  args_idx = txt.find("Arguments", purpose_idx)
89  func_idx = txt.rfind('extern "C"', 1, purpose_idx)
90  funcname = txt[txt.find("\n", func_idx)+1 : txt.find("(", func_idx)]
91  C_args_idx = txt.find("(", func_idx) + 1
92  # I'm counting on the fact that there is no ')' in arg list
93  C_args = parse_args(txt[C_args_idx : txt.find(")", C_args_idx)])
94 
95  details_idx = txt.find(" Further Details", args_idx)
96 
97  eoc_idx = txt.find("*/", args_idx)
98  argend_idx = eoc_idx
99  if details_idx > 0:
100  argend_idx = details_idx
101 
102  if details_idx > 0:
103  details_idx = txt.find("\n", details_idx + 30) + 1
104 
105  if details_idx > 0:
106  details = cleanup(txt[details_idx:eoc_idx])
107  else:
108  details = ""
109 
110  argdict = dict()
111  argname = "_____" # dummy argument name
112  argdict[argname] = list()
113 
114  # go through each "argline" in the section with arguments
115  for argline in txt[args_idx:argend_idx].split("\n"):
116  argfields = argline.split()
117 
118  switcharg = 0
119  #for inout in ("(input)", "(output)", "(input/output)", "(workspace)", "(input/workspace)", "(workspace/output)", "(input"):
120  for inout in ("input", "output", "workspace"):
121  #if len(argfields) > 1 and inout == argfields[1]:
122  if re.match(" *\w+ *\(%s" % inout, argline):
123  argname = argfields[0]
124  arginout = argline[argline.find("(") : argline.find(")")+1]
125  argtype = argline[argline.find(")")+1 :].strip()
126  argdict[argname] = [(arginout, argtype)]
127  switcharg = 1
128  break
129 
130  if not switcharg:
131  argdict[argname].append(argline)
132 
133  for key in argdict:
134  inout = argdict[key][0]
135  argdict[key] = [inout] + cleanup_lst(argdict[key][1:])
136  continue
137  l = argdict[key]
138  idx = len(l) - 1
139  fields = l[idx].split()
140  if len(fields) == 1 and is_all_char(fields[0], "="):
141  del l[idx]
142 
143  purpose = cleanup(txt[purpose_idx:args_idx])
144 
145  return FuncDoc(funcname, C_args, argdict, purpose, details)
146 
147 # this function is out of date
148 def getlatexdoc(funcdoc):
149  latexdoc = "\\textsf{magma\_int\_t} "
150  latexdoc += "\\textsf{\\textbf{%s}}" % funcdoc.funcname.replace("_", "\\_")
151  latexdoc += "(\\textsf{"
152  latexdoc += ", ".join(funcdoc.C_args).replace("_", "\\_")
153  latexdoc += "}); \\\n"
154 
155  latexdoc += "Arguments:\\\n\\begin{description}"
156 
157  for arg in funcdoc.C_args:
158  argname = ""
159  larg = len(arg)
160  for idx in range(larg):
161  ch = arg[larg-idx-1]
162  if ch.isalpha():
163  argname = ch + argname
164  else:
165  break
166 
167  latexdoc += "\\item[" + argname + "] "
168 
169  karg = argname.upper()
170  if 0 and not funcdoc.argdict.has_key(karg):
171  karg = "D" + karg
172 
173  try:
174  ldoc = funcdoc.argdict[karg]
175  latexdoc += ldoc[0] + "\n" # input/output/workspace
176  latexdoc += "\\begin{verbatim}\n"
177 
178  lidx = len(ldoc[1])
179  # remove extra indentation
180  for l in ldoc[1:]:
181  if len(l) > 0:
182  lidx = min(lidx, len(l) - len(l.lstrip()))
183 
184  for l in ldoc[1:]:
185  if l.rstrip():
186  latexdoc += l[lidx:] + "\n"
187  latexdoc += "\end{verbatim}\n"
188 
189  except:
190  #sys.stderr.write("MAGMA %s\n" % " ".join(list((funcdoc.funcname, karg, str(funcdoc.argdict.keys()), latexdoc, str(funcdoc.argdict)))))
191  pass
192 
193  latexdoc += "\n"
194 
195  latexdoc += "\\end{description}"
196 
197  return latexdoc
198 
199 class HtmlDoc:
200  def tag(self, tag, s):
201  return "<" + tag + ">" + s + "</" + tag.split()[0] + ">\n"
202 
203  def preamble(self, title):
204  return """<html>
205 <head>
206 <title>%s</title>
207 <style>
208 b {
209 font-family: sans-serif;
210 color: red;
211 }
212 em {
213 font-family: sans-serif;
214 color: blue;
215 }
216 table {
217 white-space: nowrap;
218 font-weight: bold;
219 margin-left: 6px;
220 border-top: 1px solid #A8B8D9;
221 border-left: 1px solid #A8B8D9;
222 border-right: 1px solid #A8B8D9;
223 padding: 6px 0px 6px 0px;
224 color: #253555;
225 font-weight: bold;
226 text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
227 /* firefox specific markup */
228 -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
229 -moz-border-radius-topright: 8px;
230 -moz-border-radius-topleft: 8px;
231 /* webkit specific markup */
232 -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
233 -webkit-border-top-right-radius: 8px;
234 -webkit-border-top-left-radius: 8px;
235 background-image:url('nav_f.png');
236 background-repeat:repeat-x;
237 background-color: #E2E8F2;
238 }
239 pre {background: #ffffee; border: 1px solid silver; padding: 0.5em;}
240 </style>
241 </head>
242 <body>
243 """ % title
244 
245  def epilog(self, title):
246  return """</body>
247 </html>
248 """
249 
250  def begin_decl(self):
251  return "<table>\n"
252 
253  def end_decl(self):
254  return "</table>\n"
255 
256  def ret_type(self, s):
257  return "<tr><td>" + s + " "
258  return self.tag('div class="ret_type"', s)
259 
260  def funcname(self, s):
261  return self.tag('b', s) + "</td>"
262  return self.tag('div class="funcname"', s)
263 
264  def begin_purpose(self, s):
265  return "<p><h2>%s</h2>\n<pre>\n" % s
266 
267  def end_purpose(self, s):
268  return "</pre>\n</p>\n"
269 
270  def begin_arguments(self, s):
271  return "<p><h2>%s</h2>\n" % s
272  return self.tag('div class="arguments"', s) + "<ul>\n"
273 
274  def end_arguments(self, s):
275  return "</ul>\n"
276 
277  def begin_arg(self, argname):
278  return "<li><b>" + argname + "</b>\n"
279 
280  def end_arg(self, argname):
281  return ""
282 
283  def inoutwork(self, s):
284  return s + "\n"
285 
286  def arg_type(self, s):
287  return self.tag("em", s)
288 
289  def begin_arg_desc(self, argname):
290  return "<pre>\n"
291 
292  def arg_desc_line(self, s):
293  return s + "\n"
294 
295  def end_arg_desc(self, argname):
296  return "</pre>\n</li>\n"
297 
298  def begin_details(self, s):
299  return "<p><h2>%s</h2>\n<pre>\n" % s
300 
301  def end_details(self, s):
302  return "</pre>\n</p>\n"
303 
304  def begin_args_decl(self, argcount):
305  self.argcount = argcount
306  return "<td>(</td>"
307 
308  def end_args_decl(self):
309  return "<td>)</td>\n</tr>\n"
310 
311  def decl_arg(self, prefix, argname):
312  return "<td>" + prefix + " " + self.tag("em", argname) + "<td>\n</tr>\n<tr><td></td><td></td>"
313 
314 def getoutputdoc(fdoc, output):
315  doc = output.begin_decl()
316  doc += output.ret_type("magma_int_t")
317  doc += output.funcname(fdoc.funcname)
318  doc += output.begin_args_decl(len(fdoc.C_args))
319  doc += "".join(map(lambda s: output.decl_arg(s[0], s[1]), fdoc.C_args))
320  doc += output.end_args_decl()
321  doc += output.end_decl()
322 
323  doc += output.begin_purpose("Purpose:")
324  doc += fdoc.purpose
325  doc += output.end_purpose("Purpose:")
326 
327  doc += output.begin_arguments("Arguments:")
328 
329  for arg in fdoc.C_args:
330  argname = arg[1]
331  doc += output.begin_arg(argname)
332  doc += output.end_arg(argname)
333 
334  karg = argname.upper()
335  if 0 and not funcdoc.argdict.has_key(karg):
336  karg = "D" + karg
337 
338  ldoc = fdoc.argdict.get(karg, [("(missing)", arg[0]), "MISSING"])
339  #sys.stderr.write("MAGMA %s\n" % " ".join(list((fdoc.funcname, karg, str(fdoc.argdict.keys()), doc, str(fdoc.argdict)))))
340 
341  if len(ldoc) > 1:
342  lidx = len(ldoc[1])
343  else:
344  lidx = 0
345  # remove extra indentation
346  for l in ldoc[1:]:
347  if len(l) > 0:
348  lidx = min(lidx, len(l) - len(l.lstrip()))
349 
350  doc += output.inoutwork(ldoc[0][0]) # input/output/workspace
351  doc += output.arg_type(ldoc[0][1])
352  doc += output.begin_arg_desc(argname)
353 
354  for l in ldoc[1:]:
355  if l.rstrip():
356  doc += output.arg_desc_line(l[lidx:])
357 
358  doc += output.end_arg_desc(argname)
359 
360 
361  doc += output.end_arguments("Arguments:")
362 
363  if fdoc.details:
364  doc += output.begin_details("Further Details:")
365  doc += fdoc.details
366  doc += output.end_details("Further Details:")
367 
368  return doc
369 
370 def main(argv):
371  outdir = "htmldoc"
372 
373  if not os.path.exists(outdir):
374  os.mkdir(outdir)
375 
376  fl = list()
377  for fname in argv[1:]:
378  ofname = os.path.basename(fname).replace("cpp", "html")
379  of = open(os.path.join(outdir, ofname), "w")
380 
381  odoc = HtmlDoc()
382 
383  of.write(odoc.preamble("MAGMA"))
384 
385  funcdoc = getdoc(fname)
386  #latexdoc = getlatexdoc(funcdoc)
387  doc = getoutputdoc(funcdoc, odoc)
388  of.write(doc)
389  of.write(odoc.epilog("MAGMA"))
390 
391  fl.append((funcdoc.funcname, ofname))
392 
393  idxf = open(os.path.join(outdir, "index.html"), "w")
394  idxf.write("<html>\n<head><title>MAGMA 1.0</title></head>\n<body>\n<h1>MAGMA 1.0 Function Index</h1><ul>\n")
395  for t in fl:
396  funcname, ofname = t
397  idxf.write("""<li><a href="%s"><code>%s</code></a></li>\n""" % (ofname, funcname))
398  idxf.write("</ul>\n</body>\n</html>\n")
399 
400  return 0
401 
402 if "__main__" == __name__ :
403  sys.exit(main(sys.argv))