shelldocs.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #!/usr/bin/python
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import re
  15. import sys
  16. import string
  17. from optparse import OptionParser
  18. asflicense='''
  19. <!---
  20. # Licensed to the Apache Software Foundation (ASF) under one
  21. # or more contributor license agreements. See the NOTICE file
  22. # distributed with this work for additional information
  23. # regarding copyright ownership. The ASF licenses this file
  24. # to you under the Apache License, Version 2.0 (the
  25. # "License"); you may not use this file except in compliance
  26. # with the License. You may obtain a copy of the License at
  27. #
  28. # http://www.apache.org/licenses/LICENSE-2.0
  29. #
  30. # Unless required by applicable law or agreed to in writing, software
  31. # distributed under the License is distributed on an "AS IS" BASIS,
  32. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  33. # See the License for the specific language governing permissions and
  34. # limitations under the License.
  35. -->
  36. '''
  37. def docstrip(key,string):
  38. string=re.sub("^## @%s " % key ,"",string)
  39. string=string.lstrip()
  40. string=string.rstrip()
  41. return string
  42. def toc(list):
  43. tocout=[]
  44. header=()
  45. for i in list:
  46. if header != i.getinter():
  47. header=i.getinter()
  48. line=" * %s\n" % (i.headerbuild())
  49. tocout.append(line)
  50. line=" * [%s](#%s)\n" % (i.getname().replace("_","\_"),i.getname())
  51. tocout.append(line)
  52. return tocout
  53. class ShellFunction:
  54. def __init__(self):
  55. self.reset()
  56. def __cmp__(self,other):
  57. if (self.audience == other.audience):
  58. if (self.stability == other.stability):
  59. if (self.replaceb == other.replaceb):
  60. return(cmp(self.name,other.name))
  61. else:
  62. if (self.replaceb == "Yes"):
  63. return -1
  64. else:
  65. return 1
  66. else:
  67. if (self.stability == "Stable"):
  68. return -1
  69. else:
  70. return 1
  71. else:
  72. if (self.audience == "Public"):
  73. return -1
  74. else:
  75. return 1
  76. def reset(self):
  77. self.name=None
  78. self.audience=None
  79. self.stability=None
  80. self.replaceb=None
  81. self.returnt=None
  82. self.desc=None
  83. self.params=None
  84. def setname(self,text):
  85. definition=text.split();
  86. self.name=definition[1]
  87. def getname(self):
  88. if (self.name is None):
  89. return "None"
  90. else:
  91. return self.name
  92. def setaudience(self,text):
  93. self.audience=docstrip("audience",text)
  94. self.audience=self.audience.capitalize()
  95. def getaudience(self):
  96. if (self.audience is None):
  97. return "None"
  98. else:
  99. return self.audience
  100. def setstability(self,text):
  101. self.stability=docstrip("stability",text)
  102. self.stability=self.stability.capitalize()
  103. def getstability(self):
  104. if (self.stability is None):
  105. return "None"
  106. else:
  107. return self.stability
  108. def setreplace(self,text):
  109. self.replaceb=docstrip("replaceable",text)
  110. self.replaceb=self.replaceb.capitalize()
  111. def getreplace(self):
  112. if (self.replaceb is None):
  113. return "None"
  114. else:
  115. return self.replaceb
  116. def getinter(self):
  117. return( (self.getaudience(), self.getstability(), self.getreplace()))
  118. def addreturn(self,text):
  119. if (self.returnt is None):
  120. self.returnt = []
  121. self.returnt.append(docstrip("return",text))
  122. def getreturn(self):
  123. if (self.returnt is None):
  124. return "Nothing"
  125. else:
  126. return "\n\n".join(self.returnt)
  127. def adddesc(self,text):
  128. if (self.desc is None):
  129. self.desc = []
  130. self.desc.append(docstrip("description",text))
  131. def getdesc(self):
  132. if (self.desc is None):
  133. return "None"
  134. else:
  135. return " ".join(self.desc)
  136. def addparam(self,text):
  137. if (self.params is None):
  138. self.params = []
  139. self.params.append(docstrip("param",text))
  140. def getparams(self):
  141. if (self.params is None):
  142. return ""
  143. else:
  144. return " ".join(self.params)
  145. def getusage(self):
  146. line="%s %s" % (self.name, self.getparams())
  147. return line
  148. def headerbuild(self):
  149. if self.getreplace() == "Yes":
  150. replacetext="Replaceable"
  151. else:
  152. replacetext="Not Replaceable"
  153. line="%s/%s/%s" % (self.getaudience(), self.getstability(), replacetext)
  154. return(line)
  155. def getdocpage(self):
  156. line="### `%s`\n\n"\
  157. "* Synopsis\n\n"\
  158. "```\n%s\n"\
  159. "```\n\n" \
  160. "* Description\n\n" \
  161. "%s\n\n" \
  162. "* Returns\n\n" \
  163. "%s\n\n" \
  164. "| Classification | Level |\n" \
  165. "| :--- | :--- |\n" \
  166. "| Audience | %s |\n" \
  167. "| Stability | %s |\n" \
  168. "| Replaceable | %s |\n\n" \
  169. % (self.getname(),
  170. self.getusage(),
  171. self.getdesc(),
  172. self.getreturn(),
  173. self.getaudience(),
  174. self.getstability(),
  175. self.getreplace())
  176. return line
  177. def __str__(self):
  178. line="{%s %s %s %s}" \
  179. % (self.getname(),
  180. self.getaudience(),
  181. self.getstability(),
  182. self.getreplace())
  183. return line
  184. def main():
  185. parser=OptionParser(usage="usage: %prog --skipprnorep --output OUTFILE --input INFILE [--input INFILE ...]")
  186. parser.add_option("-o","--output", dest="outfile",
  187. action="store", type="string",
  188. help="file to create", metavar="OUTFILE")
  189. parser.add_option("-i","--input", dest="infile",
  190. action="append", type="string",
  191. help="file to read", metavar="INFILE")
  192. parser.add_option("--skipprnorep", dest="skipprnorep",
  193. action="store_true", help="Skip Private & Not Replaceable")
  194. (options, args)=parser.parse_args()
  195. allfuncs=[]
  196. for filename in options.infile:
  197. with open(filename,"r") as shellcode:
  198. funcdef=ShellFunction()
  199. for line in shellcode:
  200. if line.startswith('## @description'):
  201. funcdef.adddesc(line)
  202. elif line.startswith('## @audience'):
  203. funcdef.setaudience(line)
  204. elif line.startswith('## @stability'):
  205. funcdef.setstability(line)
  206. elif line.startswith('## @replaceable'):
  207. funcdef.setreplace(line)
  208. elif line.startswith('## @param'):
  209. funcdef.addparam(line)
  210. elif line.startswith('## @return'):
  211. funcdef.addreturn(line)
  212. elif line.startswith('function'):
  213. funcdef.setname(line)
  214. if options.skipprnorep and \
  215. funcdef.getaudience() == "Private" and \
  216. funcdef.getreplace() == "No":
  217. pass
  218. else:
  219. allfuncs.append(funcdef)
  220. funcdef=ShellFunction()
  221. allfuncs=sorted(allfuncs)
  222. outfile=open(options.outfile, "w")
  223. outfile.write(asflicense)
  224. for line in toc(allfuncs):
  225. outfile.write(line)
  226. outfile.write("\n------\n\n")
  227. header=[]
  228. for funcs in allfuncs:
  229. if header != funcs.getinter():
  230. header=funcs.getinter()
  231. line="## %s\n" % (funcs.headerbuild())
  232. outfile.write(line)
  233. outfile.write(funcs.getdocpage())
  234. outfile.close()
  235. if __name__ == "__main__":
  236. main()