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