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