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