doxygengen.py 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084
  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. """This file produce action class to generate doxygen document for edk2 codebase.
  10. The action classes are shared by GUI and command line tools.
  11. """
  12. from plugins.EdkPlugins.basemodel import doxygen
  13. import os
  14. try:
  15. import wx
  16. gInGui = True
  17. except:
  18. gInGui = False
  19. import re
  20. from plugins.EdkPlugins.edk2.model import inf
  21. from plugins.EdkPlugins.edk2.model import dec
  22. from plugins.EdkPlugins.basemodel.message import *
  23. _ignore_dir = ['.svn', '_svn', 'cvs']
  24. _inf_key_description_mapping_table = {
  25. 'INF_VERSION':'Version of INF file specification',
  26. #'BASE_NAME':'Module Name',
  27. 'FILE_GUID':'Module Guid',
  28. 'MODULE_TYPE': 'Module Type',
  29. 'VERSION_STRING': 'Module Version',
  30. 'LIBRARY_CLASS': 'Produced Library Class',
  31. 'EFI_SPECIFICATION_VERSION': 'UEFI Specification Version',
  32. 'PI_SPECIFICATION_VERSION': 'PI Specification Version',
  33. 'ENTRY_POINT': 'Module Entry Point Function',
  34. 'CONSTRUCTOR': 'Library Constructor Function'
  35. }
  36. _dec_key_description_mapping_table = {
  37. 'DEC_SPECIFICATION': 'Version of DEC file specification',
  38. 'PACKAGE_GUID': 'Package Guid'
  39. }
  40. class DoxygenAction:
  41. """This is base class for all doxygen action.
  42. """
  43. def __init__(self, doxPath, chmPath, outputPath, projname, mode='html', log=None, verbose=False):
  44. """Constructor function.
  45. @param doxPath the obosolution path of doxygen execute file.
  46. @param outputPath the obosolution output path.
  47. @param log log function for output message
  48. """
  49. self._doxPath = doxPath
  50. self._chmPath = chmPath
  51. self._outputPath = outputPath
  52. self._projname = projname
  53. self._configFile = None # doxygen config file is used by doxygen exe file
  54. self._indexPageFile = None # doxygen page file for index page.
  55. self._log = log
  56. self._mode = mode
  57. self._verbose = verbose
  58. self._doxygenCallback = None
  59. self._chmCallback = None
  60. def Log(self, message, level='info'):
  61. if self._log is not None:
  62. self._log(message, level)
  63. def IsVerbose(self):
  64. return self._verbose
  65. def Generate(self):
  66. """Generate interface called by outer directly"""
  67. self.Log(">>>>>> Start generate doxygen document for %s... Zzz....\n" % self._projname)
  68. # create doxygen config file at first
  69. self._configFile = doxygen.DoxygenConfigFile()
  70. self._configFile.SetOutputDir(self._outputPath)
  71. self._configFile.SetWarningFilePath(os.path.join(self._outputPath, 'warning.txt'))
  72. if self._mode.lower() == 'html':
  73. self._configFile.SetHtmlMode()
  74. else:
  75. self._configFile.SetChmMode()
  76. self.Log(" >>>>>> Initialize doxygen config file...Zzz...\n")
  77. self.InitializeConfigFile()
  78. self.Log(" >>>>>> Generate doxygen index page file...Zzz...\n")
  79. indexPagePath = self.GenerateIndexPage()
  80. if indexPagePath is None:
  81. self.Log("Fail to generate index page!\n", 'error')
  82. return False
  83. else:
  84. self.Log("Success to create doxygen index page file %s \n" % indexPagePath)
  85. # Add index page doxygen file to file list.
  86. self._configFile.AddFile(indexPagePath)
  87. # save config file to output path
  88. configFilePath = os.path.join(self._outputPath, self._projname + '.doxygen_config')
  89. self._configFile.Generate(configFilePath)
  90. self.Log(" <<<<<< Success Save doxygen config file to %s...\n" % configFilePath)
  91. # launch doxygen tool to generate document
  92. if self._doxygenCallback is not None:
  93. self.Log(" >>>>>> Start doxygen process...Zzz...\n")
  94. if not self._doxygenCallback(self._doxPath, configFilePath):
  95. return False
  96. else:
  97. self.Log("Fail to create doxygen process!", 'error')
  98. return False
  99. return True
  100. def InitializeConfigFile(self):
  101. """Initialize config setting for doxygen project. It will be invoked after config file
  102. object is created. Inherited class should implement it.
  103. """
  104. def GenerateIndexPage(self):
  105. """Generate doxygen index page. Inherited class should implement it."""
  106. return None
  107. def RegisterCallbackDoxygenProcess(self, callback):
  108. self._doxygenCallback = callback
  109. def RegisterCallbackCHMProcess(self, callback):
  110. self._chmCallback = callback
  111. class PlatformDocumentAction(DoxygenAction):
  112. """Generate platform doxygen document, will be implement at future."""
  113. class PackageDocumentAction(DoxygenAction):
  114. """Generate package reference document"""
  115. def __init__(self, doxPath, chmPath, outputPath, pObj, mode='html', log=None, arch=None, tooltag=None,
  116. onlyInclude=False, verbose=False):
  117. DoxygenAction.__init__(self, doxPath, chmPath, outputPath, pObj.GetName(), mode, log, verbose)
  118. self._pObj = pObj
  119. self._arch = arch
  120. self._tooltag = tooltag
  121. self._onlyIncludeDocument = onlyInclude
  122. def InitializeConfigFile(self):
  123. if self._arch == 'IA32':
  124. self._configFile.AddPreDefined('MDE_CPU_IA32')
  125. elif self._arch == 'X64':
  126. self._configFile.AddPreDefined('MDE_CPU_X64')
  127. elif self._arch == 'IPF':
  128. self._configFile.AddPreDefined('MDE_CPU_IPF')
  129. elif self._arch == 'EBC':
  130. self._configFile.AddPreDefined('MDE_CPU_EBC')
  131. else:
  132. self._arch = None
  133. self._configFile.AddPreDefined('MDE_CPU_IA32')
  134. self._configFile.AddPreDefined('MDE_CPU_X64')
  135. self._configFile.AddPreDefined('MDE_CPU_IPF')
  136. self._configFile.AddPreDefined('MDE_CPU_EBC')
  137. self._configFile.AddPreDefined('MDE_CPU_ARM')
  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. with open(path, 'r') as f:
  329. lines = f.readlines()
  330. except UnicodeDecodeError:
  331. return
  332. except IOError:
  333. ErrorMsg('Fail to open file %s' % path)
  334. return
  335. configFile.AddFile(path)
  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. else:
  857. desc += '<TD>%s</TD>' % hPath
  858. desc += '</TR>'
  859. for lcObj in infObj.GetSectionObjectsByName('libraryclasses', self._arch):
  860. desc += '<TR>'
  861. desc += '<TD>%s</TD>' % lcObj.GetClass()
  862. retarr = self.SearchLibraryClassHeaderFile(lcObj.GetClass(),
  863. workspace,
  864. refDecObjs)
  865. if retarr is not None:
  866. pkgname, hPath = retarr
  867. else:
  868. self.Log('Fail find the library class %s definition from module %s dependent package!' % (lcObj.GetClass(), infObj.GetFilename()), 'error')
  869. pkgname = 'NULL'
  870. hPath = 'NULL'
  871. desc += '<TD>Consume</TD>'
  872. desc += '<TD>%s</TD>' % pkgname
  873. desc += '<TD>\link %s \endlink</TD>' % hPath
  874. desc += '</TR>'
  875. desc += "</TABLE>"
  876. section.AddDescription(desc)
  877. modPage.AddSection(section)
  878. section = doxygen.Section('SourceFiles', 'Source Files')
  879. section.AddDescription('<ul>\n')
  880. for obj in infObj.GetSourceObjects(self._arch, self._tooltag):
  881. sPath = infObj.GetModuleRootPath()
  882. sPath = os.path.join(sPath, obj.GetSourcePath()).replace('\\', '/').strip()
  883. if sPath.lower().endswith('.uni') or sPath.lower().endswith('.s') or sPath.lower().endswith('.asm') or sPath.lower().endswith('.nasm'):
  884. newPath = self.TranslateUniFile(sPath)
  885. configFile.AddFile(newPath)
  886. newPath = newPath[len(pObj.GetWorkspace()) + 1:]
  887. section.AddDescription('<li> \link %s \endlink </li>' % newPath)
  888. else:
  889. self.ProcessSourceFileForInclude(sPath, pObj, configFile, infObj)
  890. sPath = sPath[len(pObj.GetWorkspace()) + 1:]
  891. section.AddDescription('<li>\link %s \endlink </li>' % sPath)
  892. section.AddDescription('</ul>\n')
  893. modPage.AddSection(section)
  894. #sects = infObj.GetSectionByString('depex')
  895. data = []
  896. #for sect in sects:
  897. for obj in infObj.GetSectionObjectsByName('depex'):
  898. data.append(str(obj))
  899. if len(data) != 0:
  900. s = doxygen.Section('DependentSection', 'Module Dependencies')
  901. s.AddDescription('<br>'.join(data))
  902. modPage.AddSection(s)
  903. return modPage
  904. def TranslateUniFile(self, path):
  905. newpath = path + '.dox'
  906. #import core.textfile as textfile
  907. #file = textfile.TextFile(path)
  908. try:
  909. file = open(path, 'r')
  910. except (IOError, OSError) as msg:
  911. return None
  912. t = file.read()
  913. file.close()
  914. output = '/** @file \n'
  915. #output = '<html><body>'
  916. arr = t.split('\r\n')
  917. for line in arr:
  918. if line.find('@file') != -1:
  919. continue
  920. if line.find('*/') != -1:
  921. continue
  922. line = line.strip()
  923. if line.strip().startswith('/'):
  924. arr = line.split(' ')
  925. if len(arr) > 1:
  926. line = ' '.join(arr[1:])
  927. else:
  928. continue
  929. output += '%s<br>\n' % line
  930. output += '**/'
  931. if os.path.exists(newpath):
  932. os.remove(newpath)
  933. file = open(newpath, "w")
  934. file.write(output)
  935. file.close()
  936. return newpath
  937. def SearchPcdPackage(self, pcdname, workspace, decObjs):
  938. for decObj in decObjs:
  939. for pcd in decObj.GetSectionObjectsByName('pcd'):
  940. if pcdname == pcd.GetPcdName():
  941. return decObj.GetBaseName()
  942. return None
  943. def SearchProtocolPackage(self, protname, workspace, decObjs):
  944. for decObj in decObjs:
  945. for proto in decObj.GetSectionObjectsByName('protocol'):
  946. if protname == proto.GetName():
  947. return decObj.GetBaseName()
  948. return None
  949. def SearchPpiPackage(self, ppiname, workspace, decObjs):
  950. for decObj in decObjs:
  951. for ppi in decObj.GetSectionObjectsByName('ppi'):
  952. if ppiname == ppi.GetName():
  953. return decObj.GetBaseName()
  954. return None
  955. def SearchGuidPackage(self, guidname, workspace, decObjs):
  956. for decObj in decObjs:
  957. for guid in decObj.GetSectionObjectsByName('guid'):
  958. if guidname == guid.GetName():
  959. return decObj.GetBaseName()
  960. return None
  961. def SearchLibraryClassHeaderFile(self, className, workspace, decObjs):
  962. for decObj in decObjs:
  963. for cls in decObj.GetSectionObjectsByName('libraryclasses'):
  964. if cls.GetClassName().strip() == className:
  965. path = cls.GetHeaderFile().strip()
  966. path = os.path.join(decObj.GetPackageRootPath(), path)
  967. path = path[len(workspace) + 1:]
  968. return decObj.GetBaseName(), path.replace('\\', '/')
  969. return None
  970. def _ConvertPathToDoxygen(self, path, pObj):
  971. pRootPath = pObj.GetWorkspace()
  972. path = path[len(pRootPath) + 1:]
  973. return path.replace('\\', '/')
  974. def IsCHeaderFile(path):
  975. return CheckPathPostfix(path, 'h')
  976. def CheckPathPostfix(path, str):
  977. index = path.rfind('.')
  978. if index == -1:
  979. return False
  980. if path[index + 1:].lower() == str.lower():
  981. return True
  982. return False