doxygengen_spec.py 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. ## @file
  2. #
  3. # This file produce action class to generate doxygen document for edk2 codebase.
  4. # The action classes are shared by GUI and command line tools.
  5. #
  6. # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
  7. #
  8. # SPDX-License-Identifier: BSD-2-Clause-Patent
  9. from plugins.EdkPlugins.basemodel import doxygen
  10. import os
  11. try:
  12. import wx
  13. gInGui = True
  14. except:
  15. gInGui = False
  16. import re
  17. from plugins.EdkPlugins.edk2.model import inf
  18. from plugins.EdkPlugins.edk2.model import dec
  19. from plugins.EdkPlugins.basemodel.message import *
  20. _ignore_dir = ['.svn', '_svn', 'cvs']
  21. _inf_key_description_mapping_table = {
  22. 'INF_VERSION':'Version of INF file specification',
  23. #'BASE_NAME':'Module Name',
  24. 'FILE_GUID':'Module Guid',
  25. 'MODULE_TYPE': 'Module Type',
  26. 'VERSION_STRING': 'Module Version',
  27. 'LIBRARY_CLASS': 'Produced Library Class',
  28. 'EFI_SPECIFICATION_VERSION': 'UEFI Specification Version',
  29. 'PI_SPECIFICATION_VERSION': 'PI Specification Version',
  30. 'ENTRY_POINT': 'Module Entry Point Function',
  31. 'CONSTRUCTOR': 'Library Constructor Function'
  32. }
  33. _dec_key_description_mapping_table = {
  34. 'DEC_SPECIFICATION': 'Version of DEC file specification',
  35. 'PACKAGE_GUID': 'Package Guid'
  36. }
  37. class DoxygenAction:
  38. """This is base class for all doxygen action.
  39. """
  40. def __init__(self, doxPath, chmPath, outputPath, projname, mode='html', log=None, verbose=False):
  41. """Constructor function.
  42. @param doxPath the obosolution path of doxygen execute file.
  43. @param outputPath the obosolution output path.
  44. @param log log function for output message
  45. """
  46. self._doxPath = doxPath
  47. self._chmPath = chmPath
  48. self._outputPath = outputPath
  49. self._projname = projname
  50. self._configFile = None # doxygen config file is used by doxygen exe file
  51. self._indexPageFile = None # doxygen page file for index page.
  52. self._log = log
  53. self._mode = mode
  54. self._verbose = verbose
  55. self._doxygenCallback = None
  56. self._chmCallback = None
  57. def Log(self, message, level='info'):
  58. if self._log is not None:
  59. self._log(message, level)
  60. def IsVerbose(self):
  61. return self._verbose
  62. def Generate(self):
  63. """Generate interface called by outer directly"""
  64. self.Log(">>>>>> Start generate doxygen document for %s... Zzz....\n" % self._projname)
  65. # create doxygen config file at first
  66. self._configFile = doxygen.DoxygenConfigFile()
  67. self._configFile.SetOutputDir(self._outputPath)
  68. self._configFile.SetWarningFilePath(os.path.join(self._outputPath, 'warning.txt'))
  69. if self._mode.lower() == 'html':
  70. self._configFile.SetHtmlMode()
  71. else:
  72. self._configFile.SetChmMode()
  73. self.Log(" >>>>>> Initialize doxygen config file...Zzz...\n")
  74. self.InitializeConfigFile()
  75. self.Log(" >>>>>> Generate doxygen index page file...Zzz...\n")
  76. indexPagePath = self.GenerateIndexPage()
  77. if indexPagePath is None:
  78. self.Log("Fail to generate index page!\n", 'error')
  79. return False
  80. else:
  81. self.Log("Success to create doxygen index page file %s \n" % indexPagePath)
  82. # Add index page doxygen file to file list.
  83. self._configFile.AddFile(indexPagePath)
  84. # save config file to output path
  85. configFilePath = os.path.join(self._outputPath, self._projname + '.doxygen_config')
  86. self._configFile.Generate(configFilePath)
  87. self.Log(" <<<<<< Success Save doxygen config file to %s...\n" % configFilePath)
  88. # launch doxygen tool to generate document
  89. if self._doxygenCallback is not None:
  90. self.Log(" >>>>>> Start doxygen process...Zzz...\n")
  91. if not self._doxygenCallback(self._doxPath, configFilePath):
  92. return False
  93. else:
  94. self.Log("Fail to create doxygen process!", 'error')
  95. return False
  96. return True
  97. def InitializeConfigFile(self):
  98. """Initialize config setting for doxygen project. It will be invoked after config file
  99. object is created. Inherited class should implement it.
  100. """
  101. def GenerateIndexPage(self):
  102. """Generate doxygen index page. Inherited class should implement it."""
  103. return None
  104. def RegisterCallbackDoxygenProcess(self, callback):
  105. self._doxygenCallback = callback
  106. def RegisterCallbackCHMProcess(self, callback):
  107. self._chmCallback = callback
  108. class PlatformDocumentAction(DoxygenAction):
  109. """Generate platform doxygen document, will be implement at future."""
  110. class PackageDocumentAction(DoxygenAction):
  111. """Generate package reference document"""
  112. def __init__(self, doxPath, chmPath, outputPath, pObj, mode='html', log=None, arch=None, tooltag=None,
  113. macros=[], onlyInclude=False, verbose=False):
  114. DoxygenAction.__init__(self, doxPath, chmPath, outputPath, pObj.GetName(), mode, log, verbose)
  115. self._pObj = pObj
  116. self._arch = arch
  117. self._tooltag = tooltag
  118. self._macros = macros
  119. self._onlyIncludeDocument = onlyInclude
  120. def InitializeConfigFile(self):
  121. if self._arch == 'IA32':
  122. self._configFile.AddPreDefined('MDE_CPU_IA32')
  123. elif self._arch == 'X64':
  124. self._configFile.AddPreDefined('MDE_CPU_X64')
  125. elif self._arch == 'IPF':
  126. self._configFile.AddPreDefined('MDE_CPU_IPF')
  127. elif self._arch == 'EBC':
  128. self._configFile.AddPreDefined('MDE_CPU_EBC')
  129. else:
  130. self._arch = None
  131. self._configFile.AddPreDefined('MDE_CPU_IA32')
  132. self._configFile.AddPreDefined('MDE_CPU_X64')
  133. self._configFile.AddPreDefined('MDE_CPU_IPF')
  134. self._configFile.AddPreDefined('MDE_CPU_EBC')
  135. self._configFile.AddPreDefined('MDE_CPU_ARM')
  136. for macro in self._macros:
  137. self._configFile.AddPreDefined(macro)
  138. namestr = self._pObj.GetName()
  139. if self._arch is not None:
  140. namestr += '[%s]' % self._arch
  141. if self._tooltag is not None:
  142. namestr += '[%s]' % self._tooltag
  143. self._configFile.SetProjectName(namestr)
  144. self._configFile.SetStripPath(self._pObj.GetWorkspace())
  145. self._configFile.SetProjectVersion(self._pObj.GetFileObj().GetVersion())
  146. self._configFile.AddPattern('*.decdoxygen')
  147. if self._tooltag.lower() == 'msft':
  148. self._configFile.AddPreDefined('_MSC_EXTENSIONS')
  149. elif self._tooltag.lower() == 'gnu':
  150. self._configFile.AddPreDefined('__GNUC__')
  151. elif self._tooltag.lower() == 'intel':
  152. self._configFile.AddPreDefined('__INTEL_COMPILER')
  153. else:
  154. self._tooltag = None
  155. self._configFile.AddPreDefined('_MSC_EXTENSIONS')
  156. self._configFile.AddPreDefined('__GNUC__')
  157. self._configFile.AddPreDefined('__INTEL_COMPILER')
  158. self._configFile.AddPreDefined('ASM_PFX= ')
  159. self._configFile.AddPreDefined('OPTIONAL= ')
  160. def GenerateIndexPage(self):
  161. """Generate doxygen index page. Inherited class should implement it."""
  162. fObj = self._pObj.GetFileObj()
  163. pdObj = doxygen.DoxygenFile('%s Package Document' % self._pObj.GetName(),
  164. '%s.decdoxygen' % self._pObj.GetFilename())
  165. self._configFile.AddFile(pdObj.GetFilename())
  166. pdObj.AddDescription(fObj.GetFileHeader())
  167. defSection = fObj.GetSectionByName('defines')[0]
  168. baseSection = doxygen.Section('PackageBasicInformation', 'Package Basic Information')
  169. descr = '<TABLE>'
  170. for obj in defSection.GetObjects():
  171. if obj.GetKey() in _dec_key_description_mapping_table.keys():
  172. descr += '<TR>'
  173. descr += '<TD><B>%s</B></TD>' % _dec_key_description_mapping_table[obj.GetKey()]
  174. descr += '<TD>%s</TD>' % obj.GetValue()
  175. descr += '</TR>'
  176. descr += '</TABLE><br>'
  177. baseSection.AddDescription(descr)
  178. pdObj.AddSection(baseSection)
  179. knownIssueSection = doxygen.Section('Known_Issue_section', 'Known Issue')
  180. knownIssueSection.AddDescription('<ul>')
  181. knownIssueSection.AddDescription('<li> OPTIONAL macro for function parameter can not be dealed with doxygen, so it disapear in this document! </li>')
  182. knownIssueSection.AddDescription('</ul>')
  183. pdObj.AddSection(knownIssueSection)
  184. self.AddAllIncludeFiles(self._pObj, self._configFile)
  185. pages = self.GenerateIncludesSubPage(self._pObj, self._configFile)
  186. if len(pages) != 0:
  187. pdObj.AddPages(pages)
  188. pages = self.GenerateLibraryClassesSubPage(self._pObj, self._configFile)
  189. if len(pages) != 0:
  190. pdObj.AddPages(pages)
  191. pages = self.GeneratePcdSubPages(self._pObj, self._configFile)
  192. if len(pages) != 0:
  193. pdObj.AddPages(pages)
  194. pages = self.GenerateGuidSubPages(self._pObj, self._configFile)
  195. if len(pages) != 0:
  196. pdObj.AddPages(pages)
  197. pages = self.GeneratePpiSubPages(self._pObj, self._configFile)
  198. if len(pages) != 0:
  199. pdObj.AddPages(pages)
  200. pages = self.GenerateProtocolSubPages(self._pObj, self._configFile)
  201. if len(pages) != 0:
  202. pdObj.AddPages(pages)
  203. if not self._onlyIncludeDocument:
  204. pdObj.AddPages(self.GenerateModulePages(self._pObj, self._configFile))
  205. pdObj.Save()
  206. return pdObj.GetFilename()
  207. def GenerateIncludesSubPage(self, pObj, configFile):
  208. # by default add following path as include path to config file
  209. pkpath = pObj.GetFileObj().GetPackageRootPath()
  210. configFile.AddIncludePath(os.path.join(pkpath, 'Include'))
  211. configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Library'))
  212. configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Protocol'))
  213. configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Ppi'))
  214. configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Guid'))
  215. configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'IndustryStandard'))
  216. rootArray = []
  217. pageRoot = doxygen.Page("Public Includes", "%s_public_includes" % pObj.GetName())
  218. objs = pObj.GetFileObj().GetSectionObjectsByName('includes')
  219. if len(objs) == 0: return []
  220. for obj in objs:
  221. # Add path to include path
  222. path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetPath())
  223. configFile.AddIncludePath(path)
  224. # only list common folder's include file
  225. if obj.GetArch().lower() != 'common':
  226. continue
  227. bNeedAddIncludePage = False
  228. topPage = doxygen.Page(self._ConvertPathToDoxygen(path, pObj), 'public_include_top')
  229. topPage.AddDescription('<ul>\n')
  230. for file in os.listdir(path):
  231. if file.lower() in _ignore_dir: continue
  232. fullpath = os.path.join(path, file)
  233. if os.path.isfile(fullpath):
  234. self.ProcessSourceFileForInclude(fullpath, pObj, configFile)
  235. topPage.AddDescription('<li> \link %s\endlink </li>\n' % self._ConvertPathToDoxygen(fullpath, pObj))
  236. else:
  237. if file.lower() in ['library', 'protocol', 'guid', 'ppi', 'ia32', 'x64', 'ipf', 'ebc', 'arm', 'pi', 'uefi', 'aarch64']:
  238. continue
  239. bNeedAddSubPage = False
  240. subpage = doxygen.Page(self._ConvertPathToDoxygen(fullpath, pObj), 'public_include_%s' % file)
  241. subpage.AddDescription('<ul>\n')
  242. for subfile in os.listdir(fullpath):
  243. if subfile.lower() in _ignore_dir: continue
  244. bNeedAddSubPage = True
  245. subfullpath = os.path.join(fullpath, subfile)
  246. self.ProcessSourceFileForInclude(subfullpath, pObj, configFile)
  247. subpage.AddDescription('<li> \link %s \endlink </li>\n' % self._ConvertPathToDoxygen(subfullpath, pObj))
  248. subpage.AddDescription('</ul>\n')
  249. if bNeedAddSubPage:
  250. bNeedAddIncludePage = True
  251. pageRoot.AddPage(subpage)
  252. topPage.AddDescription('</ul>\n')
  253. if bNeedAddIncludePage:
  254. pageRoot.AddPage(topPage)
  255. if pageRoot.GetSubpageCount() != 0:
  256. return [pageRoot]
  257. else:
  258. return []
  259. def GenerateLibraryClassesSubPage(self, pObj, configFile):
  260. """
  261. Generate sub page for library class for package.
  262. One DEC file maybe contains many library class sections
  263. for different architecture.
  264. @param fObj DEC file object.
  265. """
  266. rootArray = []
  267. pageRoot = doxygen.Page("Library Class", "%s_libraryclass" % pObj.GetName())
  268. objs = pObj.GetFileObj().GetSectionObjectsByName('libraryclass', self._arch)
  269. if len(objs) == 0: return []
  270. if self._arch is not None:
  271. for obj in objs:
  272. classPage = doxygen.Page(obj.GetClassName(),
  273. "lc_%s" % obj.GetClassName())
  274. comments = obj.GetComment()
  275. if len(comments) != 0:
  276. classPage.AddDescription('<br>\n'.join(comments) + '<br>\n')
  277. pageRoot.AddPage(classPage)
  278. path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())
  279. path = path[len(pObj.GetWorkspace()) + 1:]
  280. if len(comments) == 0:
  281. classPage.AddDescription('\copydoc %s<p>' % obj.GetHeaderFile())
  282. section = doxygen.Section('ref', 'Refer to Header File')
  283. section.AddDescription('\link %s\n' % obj.GetHeaderFile())
  284. section.AddDescription(' \endlink<p>\n')
  285. classPage.AddSection(section)
  286. fullPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())
  287. self.ProcessSourceFileForInclude(fullPath, pObj, configFile)
  288. else:
  289. archPageDict = {}
  290. for obj in objs:
  291. if obj.GetArch() not in archPageDict.keys():
  292. archPageDict[obj.GetArch()] = doxygen.Page(obj.GetArch(),
  293. 'lc_%s' % obj.GetArch())
  294. pageRoot.AddPage(archPageDict[obj.GetArch()])
  295. subArchRoot = archPageDict[obj.GetArch()]
  296. classPage = doxygen.Page(obj.GetClassName(),
  297. "lc_%s" % obj.GetClassName())
  298. comments = obj.GetComment()
  299. if len(comments) != 0:
  300. classPage.AddDescription('<br>\n'.join(comments) + '<br>\n')
  301. subArchRoot.AddPage(classPage)
  302. path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())
  303. path = path[len(pObj.GetWorkspace()) + 1:]
  304. if len(comments) == 0:
  305. classPage.AddDescription('\copydoc %s<p>' % obj.GetHeaderFile())
  306. section = doxygen.Section('ref', 'Refer to Header File')
  307. section.AddDescription('\link %s\n' % obj.GetHeaderFile())
  308. section.AddDescription(' \endlink<p>\n')
  309. classPage.AddSection(section)
  310. fullPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())
  311. self.ProcessSourceFileForInclude(fullPath, pObj, configFile)
  312. rootArray.append(pageRoot)
  313. return rootArray
  314. def ProcessSourceFileForInclude(self, path, pObj, configFile, infObj=None):
  315. """
  316. @param path the analysising file full path
  317. @param pObj package object
  318. @param configFile doxygen config file.
  319. """
  320. if gInGui:
  321. wx.Yield()
  322. if not os.path.exists(path):
  323. ErrorMsg('Source file path %s does not exist!' % path)
  324. return
  325. if configFile.FileExists(path):
  326. return
  327. try:
  328. f = open(path, 'r')
  329. lines = f.readlines()
  330. f.close()
  331. except IOError:
  332. ErrorMsg('Fail to open file %s' % path)
  333. return
  334. configFile.AddFile(path)
  335. return
  336. no = 0
  337. for no in range(len(lines)):
  338. if len(lines[no].strip()) == 0:
  339. continue
  340. if lines[no].strip()[:2] in ['##', '//', '/*', '*/']:
  341. continue
  342. index = lines[no].lower().find('include')
  343. #mo = IncludePattern.finditer(lines[no].lower())
  344. mo = re.match(r"^#\s*include\s+[<\"]([\\/\w.]+)[>\"]$", lines[no].strip().lower())
  345. if not mo:
  346. continue
  347. mo = re.match(r"^[#\w\s]+[<\"]([\\/\w.]+)[>\"]$", lines[no].strip())
  348. filePath = mo.groups()[0]
  349. if filePath is None or len(filePath) == 0:
  350. continue
  351. # find header file in module's path firstly.
  352. fullPath = None
  353. if os.path.exists(os.path.join(os.path.dirname(path), filePath)):
  354. # Find the file in current directory
  355. fullPath = os.path.join(os.path.dirname(path), filePath).replace('\\', '/')
  356. else:
  357. # find in depedent package's include path
  358. incObjs = pObj.GetFileObj().GetSectionObjectsByName('includes')
  359. for incObj in incObjs:
  360. incPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), incObj.GetPath()).strip()
  361. incPath = os.path.realpath(os.path.join(incPath, filePath))
  362. if os.path.exists(incPath):
  363. fullPath = incPath
  364. break
  365. if infObj is not None:
  366. pkgInfObjs = infObj.GetSectionObjectsByName('packages')
  367. for obj in pkgInfObjs:
  368. decObj = dec.DECFile(os.path.join(pObj.GetWorkspace(), obj.GetPath()))
  369. if not decObj:
  370. ErrorMsg ('Fail to create pacakge object for %s' % obj.GetPackageName())
  371. continue
  372. if not decObj.Parse():
  373. ErrorMsg ('Fail to load package object for %s' % obj.GetPackageName())
  374. continue
  375. incObjs = decObj.GetSectionObjectsByName('includes')
  376. for incObj in incObjs:
  377. incPath = os.path.join(decObj.GetPackageRootPath(), incObj.GetPath()).replace('\\', '/')
  378. if os.path.exists(os.path.join(incPath, filePath)):
  379. fullPath = os.path.join(os.path.join(incPath, filePath))
  380. break
  381. if fullPath is not None:
  382. break
  383. if fullPath is None and self.IsVerbose():
  384. self.Log('Can not resolve header file %s for file %s in package %s\n' % (filePath, path, pObj.GetFileObj().GetFilename()), 'error')
  385. return
  386. else:
  387. fullPath = fullPath.replace('\\', '/')
  388. if self.IsVerbose():
  389. self.Log('Preprocessing: Add include file %s for file %s\n' % (fullPath, path))
  390. #LogMsg ('Preprocessing: Add include file %s for file %s' % (fullPath, path))
  391. self.ProcessSourceFileForInclude(fullPath, pObj, configFile, infObj)
  392. def AddAllIncludeFiles(self, pObj, configFile):
  393. objs = pObj.GetFileObj().GetSectionObjectsByName('includes')
  394. for obj in objs:
  395. incPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetPath())
  396. for root, dirs, files in os.walk(incPath):
  397. for dir in dirs:
  398. if dir.lower() in _ignore_dir:
  399. dirs.remove(dir)
  400. for file in files:
  401. path = os.path.normpath(os.path.join(root, file))
  402. configFile.AddFile(path.replace('/', '\\'))
  403. def GeneratePcdSubPages(self, pObj, configFile):
  404. """
  405. Generate sub pages for package's PCD definition.
  406. @param pObj package object
  407. @param configFile config file object
  408. """
  409. rootArray = []
  410. objs = pObj.GetFileObj().GetSectionObjectsByName('pcd')
  411. if len(objs) == 0:
  412. return []
  413. pcdRootPage = doxygen.Page('PCD', 'pcd_root_page')
  414. typeRootPageDict = {}
  415. typeArchRootPageDict = {}
  416. for obj in objs:
  417. if obj.GetPcdType() not in typeRootPageDict.keys():
  418. typeRootPageDict[obj.GetPcdType()] = doxygen.Page(obj.GetPcdType(), 'pcd_%s_root_page' % obj.GetPcdType())
  419. pcdRootPage.AddPage(typeRootPageDict[obj.GetPcdType()])
  420. typeRoot = typeRootPageDict[obj.GetPcdType()]
  421. if self._arch is not None:
  422. pcdPage = doxygen.Page('%s' % obj.GetPcdName(),
  423. 'pcd_%s_%s_%s' % (obj.GetPcdType(), obj.GetArch(), obj.GetPcdName().split('.')[1]))
  424. pcdPage.AddDescription('<br>\n'.join(obj.GetComment()) + '<br>\n')
  425. section = doxygen.Section('PCDinformation', 'PCD Information')
  426. desc = '<TABLE>'
  427. desc += '<TR>'
  428. desc += '<TD><CAPTION>Name</CAPTION></TD>'
  429. desc += '<TD><CAPTION>Token Space</CAPTION></TD>'
  430. desc += '<TD><CAPTION>Token number</CAPTION></TD>'
  431. desc += '<TD><CAPTION>Data Type</CAPTION></TD>'
  432. desc += '<TD><CAPTION>Default Value</CAPTION></TD>'
  433. desc += '</TR>'
  434. desc += '<TR>'
  435. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[1]
  436. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[0]
  437. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdToken()
  438. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdDataType()
  439. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdValue()
  440. desc += '</TR>'
  441. desc += '</TABLE>'
  442. section.AddDescription(desc)
  443. pcdPage.AddSection(section)
  444. typeRoot.AddPage(pcdPage)
  445. else:
  446. keystr = obj.GetPcdType() + obj.GetArch()
  447. if keystr not in typeArchRootPageDict.keys():
  448. typeArchRootPage = doxygen.Page(obj.GetArch(), 'pcd_%s_%s_root_page' % (obj.GetPcdType(), obj.GetArch()))
  449. typeArchRootPageDict[keystr] = typeArchRootPage
  450. typeRoot.AddPage(typeArchRootPage)
  451. typeArchRoot = typeArchRootPageDict[keystr]
  452. pcdPage = doxygen.Page('%s' % obj.GetPcdName(),
  453. 'pcd_%s_%s_%s' % (obj.GetPcdType(), obj.GetArch(), obj.GetPcdName().split('.')[1]))
  454. pcdPage.AddDescription('<br>\n'.join(obj.GetComment()) + '<br>\n')
  455. section = doxygen.Section('PCDinformation', 'PCD Information')
  456. desc = '<TABLE>'
  457. desc += '<TR>'
  458. desc += '<TD><CAPTION>Name</CAPTION></TD>'
  459. desc += '<TD><CAPTION>Token Space</CAPTION></TD>'
  460. desc += '<TD><CAPTION>Token number</CAPTION></TD>'
  461. desc += '<TD><CAPTION>Data Type</CAPTION></TD>'
  462. desc += '<TD><CAPTION>Default Value</CAPTION></TD>'
  463. desc += '</TR>'
  464. desc += '<TR>'
  465. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[1]
  466. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[0]
  467. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdToken()
  468. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdDataType()
  469. desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdValue()
  470. desc += '</TR>'
  471. desc += '</TABLE>'
  472. section.AddDescription(desc)
  473. pcdPage.AddSection(section)
  474. typeArchRoot.AddPage(pcdPage)
  475. return [pcdRootPage]
  476. def _GenerateGuidSubPage(self, pObj, obj, configFile):
  477. guidPage = doxygen.Page('%s' % obj.GetName(),
  478. 'guid_%s_%s' % (obj.GetArch(), obj.GetName()))
  479. comments = obj.GetComment()
  480. if len(comments) != 0:
  481. guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')
  482. section = doxygen.Section('BasicGuidInfo', 'GUID Information')
  483. desc = '<TABLE>'
  484. desc += '<TR>'
  485. desc += '<TD><CAPTION>GUID\'s Guid Name</CAPTION></TD><TD><CAPTION>GUID\'s Guid</CAPTION></TD>'
  486. desc += '</TR>'
  487. desc += '<TR>'
  488. desc += '<TD>%s</TD>' % obj.GetName()
  489. desc += '<TD>%s</TD>' % obj.GetGuid()
  490. desc += '</TR>'
  491. desc += '</TABLE>'
  492. section.AddDescription(desc)
  493. guidPage.AddSection(section)
  494. refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)
  495. if refFile:
  496. relPath = refFile[len(pObj.GetWorkspace()) + 1:]
  497. if len(comments) == 0:
  498. guidPage.AddDescription(' \\copydoc %s <br>' % relPath)
  499. section = doxygen.Section('ref', 'Refer to Header File')
  500. section.AddDescription('\link %s\n' % relPath)
  501. section.AddDescription('\endlink\n')
  502. self.ProcessSourceFileForInclude(refFile, pObj, configFile)
  503. guidPage.AddSection(section)
  504. return guidPage
  505. def GenerateGuidSubPages(self, pObj, configFile):
  506. """
  507. Generate sub pages for package's GUID definition.
  508. @param pObj package object
  509. @param configFilf doxygen config file object
  510. """
  511. pageRoot = doxygen.Page('GUID', 'guid_root_page')
  512. objs = pObj.GetFileObj().GetSectionObjectsByName('guids', self._arch)
  513. if len(objs) == 0: return []
  514. if self._arch is not None:
  515. for obj in objs:
  516. pageRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, configFile))
  517. else:
  518. guidArchRootPageDict = {}
  519. for obj in objs:
  520. if obj.GetArch() not in guidArchRootPageDict.keys():
  521. guidArchRoot = doxygen.Page(obj.GetArch(), 'guid_arch_root_%s' % obj.GetArch())
  522. pageRoot.AddPage(guidArchRoot)
  523. guidArchRootPageDict[obj.GetArch()] = guidArchRoot
  524. guidArchRoot = guidArchRootPageDict[obj.GetArch()]
  525. guidArchRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, configFile))
  526. return [pageRoot]
  527. def _GeneratePpiSubPage(self, pObj, obj, configFile):
  528. guidPage = doxygen.Page(obj.GetName(), 'ppi_page_%s' % obj.GetName())
  529. comments = obj.GetComment()
  530. if len(comments) != 0:
  531. guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')
  532. section = doxygen.Section('BasicPpiInfo', 'PPI Information')
  533. desc = '<TABLE>'
  534. desc += '<TR>'
  535. desc += '<TD><CAPTION>PPI\'s Guid Name</CAPTION></TD><TD><CAPTION>PPI\'s Guid</CAPTION></TD>'
  536. desc += '</TR>'
  537. desc += '<TR>'
  538. desc += '<TD>%s</TD>' % obj.GetName()
  539. desc += '<TD>%s</TD>' % obj.GetGuid()
  540. desc += '</TR>'
  541. desc += '</TABLE>'
  542. section.AddDescription(desc)
  543. guidPage.AddSection(section)
  544. refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)
  545. if refFile:
  546. relPath = refFile[len(pObj.GetWorkspace()) + 1:]
  547. if len(comments) == 0:
  548. guidPage.AddDescription(' \\copydoc %s <br>' % relPath)
  549. section = doxygen.Section('ref', 'Refer to Header File')
  550. section.AddDescription('\link %s\n' % relPath)
  551. section.AddDescription('\endlink\n')
  552. self.ProcessSourceFileForInclude(refFile, pObj, configFile)
  553. guidPage.AddSection(section)
  554. return guidPage
  555. def GeneratePpiSubPages(self, pObj, configFile):
  556. """
  557. Generate sub pages for package's GUID definition.
  558. @param pObj package object
  559. @param configFilf doxygen config file object
  560. """
  561. pageRoot = doxygen.Page('PPI', 'ppi_root_page')
  562. objs = pObj.GetFileObj().GetSectionObjectsByName('ppis', self._arch)
  563. if len(objs) == 0: return []
  564. if self._arch is not None:
  565. for obj in objs:
  566. pageRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, configFile))
  567. else:
  568. guidArchRootPageDict = {}
  569. for obj in objs:
  570. if obj.GetArch() not in guidArchRootPageDict.keys():
  571. guidArchRoot = doxygen.Page(obj.GetArch(), 'ppi_arch_root_%s' % obj.GetArch())
  572. pageRoot.AddPage(guidArchRoot)
  573. guidArchRootPageDict[obj.GetArch()] = guidArchRoot
  574. guidArchRoot = guidArchRootPageDict[obj.GetArch()]
  575. guidArchRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, configFile))
  576. return [pageRoot]
  577. def _GenerateProtocolSubPage(self, pObj, obj, configFile):
  578. guidPage = doxygen.Page(obj.GetName(), 'protocol_page_%s' % obj.GetName())
  579. comments = obj.GetComment()
  580. if len(comments) != 0:
  581. guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')
  582. section = doxygen.Section('BasicProtocolInfo', 'PROTOCOL Information')
  583. desc = '<TABLE>'
  584. desc += '<TR>'
  585. desc += '<TD><CAPTION>PROTOCOL\'s Guid Name</CAPTION></TD><TD><CAPTION>PROTOCOL\'s Guid</CAPTION></TD>'
  586. desc += '</TR>'
  587. desc += '<TR>'
  588. desc += '<TD>%s</TD>' % obj.GetName()
  589. desc += '<TD>%s</TD>' % obj.GetGuid()
  590. desc += '</TR>'
  591. desc += '</TABLE>'
  592. section.AddDescription(desc)
  593. guidPage.AddSection(section)
  594. refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)
  595. if refFile:
  596. relPath = refFile[len(pObj.GetWorkspace()) + 1:]
  597. if len(comments) == 0:
  598. guidPage.AddDescription(' \\copydoc %s <br>' % relPath)
  599. section = doxygen.Section('ref', 'Refer to Header File')
  600. section.AddDescription('\link %s\n' % relPath)
  601. section.AddDescription('\endlink\n')
  602. self.ProcessSourceFileForInclude(refFile, pObj, configFile)
  603. guidPage.AddSection(section)
  604. return guidPage
  605. def GenerateProtocolSubPages(self, pObj, configFile):
  606. """
  607. Generate sub pages for package's GUID definition.
  608. @param pObj package object
  609. @param configFilf doxygen config file object
  610. """
  611. pageRoot = doxygen.Page('PROTOCOL', 'protocol_root_page')
  612. objs = pObj.GetFileObj().GetSectionObjectsByName('protocols', self._arch)
  613. if len(objs) == 0: return []
  614. if self._arch is not None:
  615. for obj in objs:
  616. pageRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, configFile))
  617. else:
  618. guidArchRootPageDict = {}
  619. for obj in objs:
  620. if obj.GetArch() not in guidArchRootPageDict.keys():
  621. guidArchRoot = doxygen.Page(obj.GetArch(), 'protocol_arch_root_%s' % obj.GetArch())
  622. pageRoot.AddPage(guidArchRoot)
  623. guidArchRootPageDict[obj.GetArch()] = guidArchRoot
  624. guidArchRoot = guidArchRootPageDict[obj.GetArch()]
  625. guidArchRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, configFile))
  626. return [pageRoot]
  627. def FindHeaderFileForGuid(self, pObj, name, configFile):
  628. """
  629. For declaration header file for GUID/PPI/Protocol.
  630. @param pObj package object
  631. @param name guid/ppi/protocol's name
  632. @param configFile config file object
  633. @return full path of header file and None if not found.
  634. """
  635. startPath = pObj.GetFileObj().GetPackageRootPath()
  636. incPath = os.path.join(startPath, 'Include').replace('\\', '/')
  637. # if <PackagePath>/include exist, then search header under it.
  638. if os.path.exists(incPath):
  639. startPath = incPath
  640. for root, dirs, files in os.walk(startPath):
  641. for dir in dirs:
  642. if dir.lower() in _ignore_dir:
  643. dirs.remove(dir)
  644. for file in files:
  645. fPath = os.path.join(root, file)
  646. if not IsCHeaderFile(fPath):
  647. continue
  648. try:
  649. f = open(fPath, 'r')
  650. lines = f.readlines()
  651. f.close()
  652. except IOError:
  653. self.Log('Fail to open file %s\n' % fPath)
  654. continue
  655. for line in lines:
  656. if line.find(name) != -1 and \
  657. line.find('extern') != -1:
  658. return fPath.replace('\\', '/')
  659. return None
  660. def GetPackageModuleList(self, pObj):
  661. """
  662. Get all module's INF path under package's root path
  663. @param pObj package object
  664. @return arrary of INF full path
  665. """
  666. mArray = []
  667. packPath = pObj.GetFileObj().GetPackageRootPath()
  668. if not os.path.exists:
  669. return None
  670. for root, dirs, files in os.walk(packPath):
  671. for dir in dirs:
  672. if dir.lower() in _ignore_dir:
  673. dirs.remove(dir)
  674. for file in files:
  675. if CheckPathPostfix(file, 'inf'):
  676. fPath = os.path.join(root, file).replace('\\', '/')
  677. mArray.append(fPath)
  678. return mArray
  679. def GenerateModulePages(self, pObj, configFile):
  680. """
  681. Generate sub pages for package's module which is under the package
  682. root directory.
  683. @param pObj package object
  684. @param configFilf doxygen config file object
  685. """
  686. infList = self.GetPackageModuleList(pObj)
  687. rootPages = []
  688. libObjs = []
  689. modObjs = []
  690. for infpath in infList:
  691. infObj = inf.INFFile(infpath)
  692. #infObj = INFFileObject.INFFile (pObj.GetWorkspacePath(),
  693. # inf)
  694. if not infObj:
  695. self.Log('Fail create INF object for %s' % inf)
  696. continue
  697. if not infObj.Parse():
  698. self.Log('Fail to load INF file %s' % inf)
  699. continue
  700. if infObj.GetProduceLibraryClass() is not None:
  701. libObjs.append(infObj)
  702. else:
  703. modObjs.append(infObj)
  704. if len(libObjs) != 0:
  705. libRootPage = doxygen.Page('Libraries', 'lib_root_page')
  706. rootPages.append(libRootPage)
  707. for libInf in libObjs:
  708. libRootPage.AddPage(self.GenerateModulePage(pObj, libInf, configFile, True))
  709. if len(modObjs) != 0:
  710. modRootPage = doxygen.Page('Modules', 'module_root_page')
  711. rootPages.append(modRootPage)
  712. for modInf in modObjs:
  713. modRootPage.AddPage(self.GenerateModulePage(pObj, modInf, configFile, False))
  714. return rootPages
  715. def GenerateModulePage(self, pObj, infObj, configFile, isLib):
  716. """
  717. Generate page for a module/library.
  718. @param infObj INF file object for module/library
  719. @param configFile doxygen config file object
  720. @param isLib Whether this module is libary
  721. @param module doxygen page object
  722. """
  723. workspace = pObj.GetWorkspace()
  724. refDecObjs = []
  725. for obj in infObj.GetSectionObjectsByName('packages'):
  726. decObj = dec.DECFile(os.path.join(workspace, obj.GetPath()))
  727. if not decObj:
  728. ErrorMsg ('Fail to create pacakge object for %s' % obj.GetPackageName())
  729. continue
  730. if not decObj.Parse():
  731. ErrorMsg ('Fail to load package object for %s' % obj.GetPackageName())
  732. continue
  733. refDecObjs.append(decObj)
  734. modPage = doxygen.Page('%s' % infObj.GetBaseName(),
  735. 'module_%s' % infObj.GetBaseName())
  736. modPage.AddDescription(infObj.GetFileHeader())
  737. basicInfSection = doxygen.Section('BasicModuleInformation', 'Basic Module Information')
  738. desc = "<TABLE>"
  739. for obj in infObj.GetSectionObjectsByName('defines'):
  740. key = obj.GetKey()
  741. value = obj.GetValue()
  742. if key not in _inf_key_description_mapping_table.keys(): continue
  743. if key == 'LIBRARY_CLASS' and value.find('|') != -1:
  744. clsname, types = value.split('|')
  745. desc += '<TR>'
  746. desc += '<TD><B>%s</B></TD>' % _inf_key_description_mapping_table[key]
  747. desc += '<TD>%s</TD>' % clsname
  748. desc += '</TR>'
  749. desc += '<TR>'
  750. desc += '<TD><B>Supported Module Types</B></TD>'
  751. desc += '<TD>%s</TD>' % types
  752. desc += '</TR>'
  753. else:
  754. desc += '<TR>'
  755. desc += '<TD><B>%s</B></TD>' % _inf_key_description_mapping_table[key]
  756. if key == 'EFI_SPECIFICATION_VERSION' and value == '0x00020000':
  757. value = '2.0'
  758. desc += '<TD>%s</TD>' % value
  759. desc += '</TR>'
  760. desc += '</TABLE>'
  761. basicInfSection.AddDescription(desc)
  762. modPage.AddSection(basicInfSection)
  763. # Add protocol section
  764. data = []
  765. for obj in infObj.GetSectionObjectsByName('pcd', self._arch):
  766. data.append(obj.GetPcdName().strip())
  767. if len(data) != 0:
  768. s = doxygen.Section('Pcds', 'Pcds')
  769. desc = "<TABLE>"
  770. desc += '<TR><TD><B>PCD Name</B></TD><TD><B>TokenSpace</B></TD><TD><B>Package</B></TD></TR>'
  771. for item in data:
  772. desc += '<TR>'
  773. desc += '<TD>%s</TD>' % item.split('.')[1]
  774. desc += '<TD>%s</TD>' % item.split('.')[0]
  775. pkgbasename = self.SearchPcdPackage(item, workspace, refDecObjs)
  776. desc += '<TD>%s</TD>' % pkgbasename
  777. desc += '</TR>'
  778. desc += "</TABLE>"
  779. s.AddDescription(desc)
  780. modPage.AddSection(s)
  781. # Add protocol section
  782. #sects = infObj.GetSectionByString('protocol')
  783. data = []
  784. #for sect in sects:
  785. for obj in infObj.GetSectionObjectsByName('protocol', self._arch):
  786. data.append(obj.GetName().strip())
  787. if len(data) != 0:
  788. s = doxygen.Section('Protocols', 'Protocols')
  789. desc = "<TABLE>"
  790. desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'
  791. for item in data:
  792. desc += '<TR>'
  793. desc += '<TD>%s</TD>' % item
  794. pkgbasename = self.SearchProtocolPackage(item, workspace, refDecObjs)
  795. desc += '<TD>%s</TD>' % pkgbasename
  796. desc += '</TR>'
  797. desc += "</TABLE>"
  798. s.AddDescription(desc)
  799. modPage.AddSection(s)
  800. # Add ppi section
  801. #sects = infObj.GetSectionByString('ppi')
  802. data = []
  803. #for sect in sects:
  804. for obj in infObj.GetSectionObjectsByName('ppi', self._arch):
  805. data.append(obj.GetName().strip())
  806. if len(data) != 0:
  807. s = doxygen.Section('Ppis', 'Ppis')
  808. desc = "<TABLE>"
  809. desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'
  810. for item in data:
  811. desc += '<TR>'
  812. desc += '<TD>%s</TD>' % item
  813. pkgbasename = self.SearchPpiPackage(item, workspace, refDecObjs)
  814. desc += '<TD>%s</TD>' % pkgbasename
  815. desc += '</TR>'
  816. desc += "</TABLE>"
  817. s.AddDescription(desc)
  818. modPage.AddSection(s)
  819. # Add guid section
  820. #sects = infObj.GetSectionByString('guid')
  821. data = []
  822. #for sect in sects:
  823. for obj in infObj.GetSectionObjectsByName('guid', self._arch):
  824. data.append(obj.GetName().strip())
  825. if len(data) != 0:
  826. s = doxygen.Section('Guids', 'Guids')
  827. desc = "<TABLE>"
  828. desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'
  829. for item in data:
  830. desc += '<TR>'
  831. desc += '<TD>%s</TD>' % item
  832. pkgbasename = self.SearchGuidPackage(item, workspace, refDecObjs)
  833. desc += '<TD>%s</TD>' % pkgbasename
  834. desc += '</TR>'
  835. desc += "</TABLE>"
  836. s.AddDescription(desc)
  837. modPage.AddSection(s)
  838. section = doxygen.Section('LibraryClasses', 'Library Classes')
  839. desc = "<TABLE>"
  840. desc += '<TR><TD><B>Name</B></TD><TD><B>Type</B></TD><TD><B>Package</B></TD><TD><B>Header File</B></TD></TR>'
  841. if isLib:
  842. desc += '<TR>'
  843. desc += '<TD>%s</TD>' % infObj.GetProduceLibraryClass()
  844. desc += '<TD>Produce</TD>'
  845. try:
  846. pkgname, hPath = self.SearchLibraryClassHeaderFile(infObj.GetProduceLibraryClass(),
  847. workspace,
  848. refDecObjs)
  849. except:
  850. self.Log ('fail to get package header file for lib class %s' % infObj.GetProduceLibraryClass())
  851. pkgname = 'NULL'
  852. hPath = 'NULL'
  853. desc += '<TD>%s</TD>' % pkgname
  854. if hPath != "NULL":
  855. #desc += '<TD>\link %s \endlink</TD>' % hPath
  856. desc += '<TD>%s</TD>' % hPath
  857. else:
  858. desc += '<TD>%s</TD>' % hPath
  859. desc += '</TR>'
  860. for lcObj in infObj.GetSectionObjectsByName('libraryclasses', self._arch):
  861. desc += '<TR>'
  862. desc += '<TD>%s</TD>' % lcObj.GetClass()
  863. retarr = self.SearchLibraryClassHeaderFile(lcObj.GetClass(),
  864. workspace,
  865. refDecObjs)
  866. if retarr is not None:
  867. pkgname, hPath = retarr
  868. else:
  869. self.Log('Fail find the library class %s definition from module %s dependent package!' % (lcObj.GetClass(), infObj.GetFilename()), 'error')
  870. pkgname = 'NULL'
  871. hPath = 'NULL'
  872. desc += '<TD>Consume</TD>'
  873. desc += '<TD>%s</TD>' % pkgname
  874. desc += '<TD>%s</TD>' % hPath
  875. desc += '</TR>'
  876. desc += "</TABLE>"
  877. section.AddDescription(desc)
  878. modPage.AddSection(section)
  879. section = doxygen.Section('SourceFiles', 'Source Files')
  880. section.AddDescription('<ul>\n')
  881. for obj in infObj.GetSourceObjects(self._arch, self._tooltag):
  882. sPath = infObj.GetModuleRootPath()
  883. sPath = os.path.join(sPath, obj.GetSourcePath()).replace('\\', '/').strip()
  884. if sPath.lower().endswith('.uni') or sPath.lower().endswith('.s') or sPath.lower().endswith('.asm') or sPath.lower().endswith('.nasm'):
  885. newPath = self.TranslateUniFile(sPath)
  886. configFile.AddFile(newPath)
  887. newPath = newPath[len(pObj.GetWorkspace()) + 1:]
  888. section.AddDescription('<li> \link %s \endlink </li>' % newPath)
  889. else:
  890. self.ProcessSourceFileForInclude(sPath, pObj, configFile, infObj)
  891. sPath = sPath[len(pObj.GetWorkspace()) + 1:]
  892. section.AddDescription('<li>\link %s \endlink </li>' % sPath)
  893. section.AddDescription('</ul>\n')
  894. modPage.AddSection(section)
  895. #sects = infObj.GetSectionByString('depex')
  896. data = []
  897. #for sect in sects:
  898. for obj in infObj.GetSectionObjectsByName('depex'):
  899. data.append(str(obj))
  900. if len(data) != 0:
  901. s = doxygen.Section('DependentSection', 'Module Dependencies')
  902. s.AddDescription('<br>'.join(data))
  903. modPage.AddSection(s)
  904. return modPage
  905. def TranslateUniFile(self, path):
  906. newpath = path + '.dox'
  907. #import core.textfile as textfile
  908. #file = textfile.TextFile(path)
  909. try:
  910. file = open(path, 'r')
  911. except (IOError, OSError) as msg:
  912. return None
  913. t = file.read()
  914. file.close()
  915. output = '/** @file \n'
  916. #output = '<html><body>'
  917. arr = t.split('\r\n')
  918. for line in arr:
  919. if line.find('@file') != -1:
  920. continue
  921. if line.find('*/') != -1:
  922. continue
  923. line = line.strip()
  924. if line.strip().startswith('/'):
  925. arr = line.split(' ')
  926. if len(arr) > 1:
  927. line = ' '.join(arr[1:])
  928. else:
  929. continue
  930. output += '%s<br>\n' % line
  931. output += '**/'
  932. if os.path.exists(newpath):
  933. os.remove(newpath)
  934. file = open(newpath, "w")
  935. file.write(output)
  936. file.close()
  937. return newpath
  938. def SearchPcdPackage(self, pcdname, workspace, decObjs):
  939. for decObj in decObjs:
  940. for pcd in decObj.GetSectionObjectsByName('pcd'):
  941. if pcdname == pcd.GetPcdName():
  942. return decObj.GetBaseName()
  943. return None
  944. def SearchProtocolPackage(self, protname, workspace, decObjs):
  945. for decObj in decObjs:
  946. for proto in decObj.GetSectionObjectsByName('protocol'):
  947. if protname == proto.GetName():
  948. return decObj.GetBaseName()
  949. return None
  950. def SearchPpiPackage(self, ppiname, workspace, decObjs):
  951. for decObj in decObjs:
  952. for ppi in decObj.GetSectionObjectsByName('ppi'):
  953. if ppiname == ppi.GetName():
  954. return decObj.GetBaseName()
  955. return None
  956. def SearchGuidPackage(self, guidname, workspace, decObjs):
  957. for decObj in decObjs:
  958. for guid in decObj.GetSectionObjectsByName('guid'):
  959. if guidname == guid.GetName():
  960. return decObj.GetBaseName()
  961. return None
  962. def SearchLibraryClassHeaderFile(self, className, workspace, decObjs):
  963. for decObj in decObjs:
  964. for cls in decObj.GetSectionObjectsByName('libraryclasses'):
  965. if cls.GetClassName().strip() == className:
  966. path = cls.GetHeaderFile().strip()
  967. path = os.path.join(decObj.GetPackageRootPath(), path)
  968. path = path[len(workspace) + 1:]
  969. return decObj.GetBaseName(), path.replace('\\', '/')
  970. return None
  971. def _ConvertPathToDoxygen(self, path, pObj):
  972. pRootPath = pObj.GetWorkspace()
  973. path = path[len(pRootPath) + 1:]
  974. return path.replace('\\', '/')
  975. def IsCHeaderFile(path):
  976. return CheckPathPostfix(path, 'h')
  977. def CheckPathPostfix(path, str):
  978. index = path.rfind('.')
  979. if index == -1:
  980. return False
  981. if path[index + 1:].lower() == str.lower():
  982. return True
  983. return False