#!/usr/bin/python # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import re import sys import string from optparse import OptionParser asflicense=''' ''' def docstrip(key,string): string=re.sub("^## @%s " % key ,"",string) string=string.lstrip() string=string.rstrip() return string def toc(list): tocout=[] header=() for i in list: if header != i.getinter(): header=i.getinter() line=" * %s\n" % (i.headerbuild()) tocout.append(line) line=" * [%s](#%s)\n" % (i.getname().replace("_","\_"),i.getname()) tocout.append(line) return tocout class ShellFunction: def __init__(self): self.reset() def __cmp__(self,other): if (self.audience == other.audience): if (self.stability == other.stability): if (self.replaceb == other.replaceb): return(cmp(self.name,other.name)) else: if (self.replaceb == "Yes"): return -1 else: return 1 else: if (self.stability == "Stable"): return -1 else: return 1 else: if (self.audience == "Public"): return -1 else: return 1 def reset(self): self.name=None self.audience=None self.stability=None self.replaceb=None self.returnt=None self.desc=None self.params=None def setname(self,text): definition=text.split(); self.name=definition[1] def getname(self): if (self.name is None): return "None" else: return self.name def setaudience(self,text): self.audience=docstrip("audience",text) self.audience=self.audience.capitalize() def getaudience(self): if (self.audience is None): return "None" else: return self.audience def setstability(self,text): self.stability=docstrip("stability",text) self.stability=self.stability.capitalize() def getstability(self): if (self.stability is None): return "None" else: return self.stability def setreplace(self,text): self.replaceb=docstrip("replaceable",text) self.replaceb=self.replaceb.capitalize() def getreplace(self): if (self.replaceb is None): return "None" else: return self.replaceb def getinter(self): return( (self.getaudience(), self.getstability(), self.getreplace())) def addreturn(self,text): if (self.returnt is None): self.returnt = [] self.returnt.append(docstrip("return",text)) def getreturn(self): if (self.returnt is None): return "Nothing" else: return "\n\n".join(self.returnt) def adddesc(self,text): if (self.desc is None): self.desc = [] self.desc.append(docstrip("description",text)) def getdesc(self): if (self.desc is None): return "None" else: return " ".join(self.desc) def addparam(self,text): if (self.params is None): self.params = [] self.params.append(docstrip("param",text)) def getparams(self): if (self.params is None): return "" else: return " ".join(self.params) def getusage(self): line="%s %s" % (self.name, self.getparams()) return line def headerbuild(self): if self.getreplace() == "Yes": replacetext="Replaceable" else: replacetext="Not Replaceable" line="%s/%s/%s" % (self.getaudience(), self.getstability(), replacetext) return(line) def getdocpage(self): line="### `%s`\n\n"\ "* Synopsis\n\n"\ "```\n%s\n"\ "```\n\n" \ "* Description\n\n" \ "%s\n\n" \ "* Returns\n\n" \ "%s\n\n" \ "| Classification | Level |\n" \ "| :--- | :--- |\n" \ "| Audience | %s |\n" \ "| Stability | %s |\n" \ "| Replaceable | %s |\n\n" \ % (self.getname(), self.getusage(), self.getdesc(), self.getreturn(), self.getaudience(), self.getstability(), self.getreplace()) return line def __str__(self): line="{%s %s %s %s}" \ % (self.getname(), self.getaudience(), self.getstability(), self.getreplace()) return line def main(): parser=OptionParser(usage="usage: %prog --skipprnorep --output OUTFILE --input INFILE [--input INFILE ...]") parser.add_option("-o","--output", dest="outfile", action="store", type="string", help="file to create", metavar="OUTFILE") parser.add_option("-i","--input", dest="infile", action="append", type="string", help="file to read", metavar="INFILE") parser.add_option("--skipprnorep", dest="skipprnorep", action="store_true", help="Skip Private & Not Replaceable") (options, args)=parser.parse_args() allfuncs=[] for filename in options.infile: with open(filename,"r") as shellcode: funcdef=ShellFunction() for line in shellcode: if line.startswith('## @description'): funcdef.adddesc(line) elif line.startswith('## @audience'): funcdef.setaudience(line) elif line.startswith('## @stability'): funcdef.setstability(line) elif line.startswith('## @replaceable'): funcdef.setreplace(line) elif line.startswith('## @param'): funcdef.addparam(line) elif line.startswith('## @return'): funcdef.addreturn(line) elif line.startswith('function'): funcdef.setname(line) if options.skipprnorep and \ funcdef.getaudience() == "Private" and \ funcdef.getreplace() == "No": pass else: allfuncs.append(funcdef) funcdef=ShellFunction() allfuncs=sorted(allfuncs) outfile=open(options.outfile, "w") outfile.write(asflicense) for line in toc(allfuncs): outfile.write(line) outfile.write("\n------\n\n") header=[] for funcs in allfuncs: if header != funcs.getinter(): header=funcs.getinter() line="## %s\n" % (funcs.headerbuild()) outfile.write(line) outfile.write(funcs.getdocpage()) outfile.close() if __name__ == "__main__": main()