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