]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/doxygengen_spec.py
BaseTools: Add PackageDocumentTools into Scripts folder
[mirror_edk2.git] / BaseTools / Scripts / PackageDocumentTools / plugins / EdkPlugins / edk2 / model / doxygengen_spec.py
diff --git a/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/doxygengen_spec.py b/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/edk2/model/doxygengen_spec.py
new file mode 100644 (file)
index 0000000..876da13
--- /dev/null
@@ -0,0 +1,1092 @@
+## @file\r
+#\r
+# This file produce action class to generate doxygen document for edk2 codebase.\r
+# The action classes are shared by GUI and command line tools.\r
+#\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+import plugins.EdkPlugins.basemodel.doxygen as doxygen\r
+import os\r
+try:\r
+    import wx\r
+    gInGui = True\r
+except:\r
+    gInGui = False\r
+import re\r
+import plugins.EdkPlugins.edk2.model.inf as inf\r
+import plugins.EdkPlugins.edk2.model.dec as dec\r
+from plugins.EdkPlugins.basemodel.message import *\r
+\r
+_ignore_dir = ['.svn', '_svn', 'cvs']\r
+_inf_key_description_mapping_table = {\r
+  'INF_VERSION':'Version of INF file specification',\r
+  #'BASE_NAME':'Module Name',\r
+  'FILE_GUID':'Module Guid',\r
+  'MODULE_TYPE': 'Module Type',\r
+  'VERSION_STRING': 'Module Version',\r
+  'LIBRARY_CLASS': 'Produced Library Class',\r
+  'EFI_SPECIFICATION_VERSION': 'UEFI Specification Version',\r
+  'PI_SPECIFICATION_VERSION': 'PI Specification Version',\r
+  'ENTRY_POINT': 'Module Entry Point Function',\r
+  'CONSTRUCTOR': 'Library Constructor Function'\r
+}\r
+\r
+_dec_key_description_mapping_table = {\r
+  'DEC_SPECIFICATION': 'Version of DEC file specification',\r
+  'PACKAGE_GUID': 'Package Guid'\r
+}\r
+class DoxygenAction:\r
+    """This is base class for all doxygen action.\r
+    """\r
+\r
+    def __init__(self, doxPath, chmPath, outputPath, projname, mode='html', log=None, verbose=False):\r
+        """Constructor function.\r
+        @param  doxPath         the obosolution path of doxygen execute file.\r
+        @param  outputPath      the obosolution output path.\r
+        @param  log             log function for output message\r
+        """\r
+        self._doxPath       = doxPath\r
+        self._chmPath       = chmPath\r
+        self._outputPath    = outputPath\r
+        self._projname      = projname\r
+        self._configFile    = None          # doxygen config file is used by doxygen exe file\r
+        self._indexPageFile = None          # doxygen page file for index page.\r
+        self._log           = log\r
+        self._mode          = mode\r
+        self._verbose       = verbose\r
+        self._doxygenCallback = None\r
+        self._chmCallback     = None\r
+\r
+    def Log(self, message, level='info'):\r
+        if self._log != None:\r
+            self._log(message, level)\r
+\r
+    def IsVerbose(self):\r
+        return self._verbose\r
+\r
+    def Generate(self):\r
+        """Generate interface called by outer directly"""\r
+        self.Log(">>>>>> Start generate doxygen document for %s... Zzz....\n" % self._projname)\r
+\r
+        # create doxygen config file at first\r
+        self._configFile = doxygen.DoxygenConfigFile()\r
+        self._configFile.SetOutputDir(self._outputPath)\r
+\r
+        self._configFile.SetWarningFilePath(os.path.join(self._outputPath, 'warning.txt'))\r
+        if self._mode.lower() == 'html':\r
+            self._configFile.SetHtmlMode()\r
+        else:\r
+            self._configFile.SetChmMode()\r
+\r
+        self.Log("    >>>>>> Initialize doxygen config file...Zzz...\n")\r
+        self.InitializeConfigFile()\r
+\r
+        self.Log("    >>>>>> Generate doxygen index page file...Zzz...\n")\r
+        indexPagePath = self.GenerateIndexPage()\r
+        if indexPagePath == None:\r
+            self.Log("Fail to generate index page!\n", 'error')\r
+            return False\r
+        else:\r
+            self.Log("Success to create doxygen index page file %s \n" % indexPagePath)\r
+\r
+        # Add index page doxygen file to file list.\r
+        self._configFile.AddFile(indexPagePath)\r
+\r
+        # save config file to output path\r
+        configFilePath = os.path.join(self._outputPath, self._projname + '.doxygen_config')\r
+        self._configFile.Generate(configFilePath)\r
+        self.Log("    <<<<<< Success Save doxygen config file to %s...\n" % configFilePath)\r
+\r
+        # launch doxygen tool to generate document\r
+        if self._doxygenCallback != None:\r
+            self.Log("    >>>>>> Start doxygen process...Zzz...\n")\r
+            if not self._doxygenCallback(self._doxPath, configFilePath):\r
+                return False\r
+        else:\r
+            self.Log("Fail to create doxygen process!", 'error')\r
+            return False\r
+\r
+        return True\r
+\r
+    def InitializeConfigFile(self):\r
+        """Initialize config setting for doxygen project. It will be invoked after config file\r
+           object is created. Inherited class should implement it.\r
+        """\r
+\r
+    def GenerateIndexPage(self):\r
+        """Generate doxygen index page. Inherited class should implement it."""\r
+        return None\r
+\r
+    def RegisterCallbackDoxygenProcess(self, callback):\r
+        self._doxygenCallback = callback\r
+\r
+    def RegisterCallbackCHMProcess(self, callback):\r
+        self._chmCallback = callback\r
+\r
+class PlatformDocumentAction(DoxygenAction):\r
+    """Generate platform doxygen document, will be implement at future."""\r
+\r
+class PackageDocumentAction(DoxygenAction):\r
+    """Generate package reference document"""\r
+\r
+    def __init__(self, doxPath, chmPath, outputPath, pObj, mode='html', log=None, arch=None, tooltag=None,\r
+                 macros=[], onlyInclude=False, verbose=False):\r
+        DoxygenAction.__init__(self, doxPath, chmPath, outputPath, pObj.GetName(), mode, log, verbose)\r
+        self._pObj   = pObj\r
+        self._arch   = arch\r
+        self._tooltag = tooltag\r
+        self._macros = macros\r
+        self._onlyIncludeDocument = onlyInclude\r
+\r
+    def InitializeConfigFile(self):\r
+        if self._arch == 'IA32':\r
+            self._configFile.AddPreDefined('MDE_CPU_IA32')\r
+        elif self._arch == 'X64':\r
+            self._configFile.AddPreDefined('MDE_CPU_X64')\r
+        elif self._arch == 'IPF':\r
+            self._configFile.AddPreDefined('MDE_CPU_IPF')\r
+        elif self._arch == 'EBC':\r
+            self._configFile.AddPreDefined('MDE_CPU_EBC')\r
+        else:\r
+            self._arch = None\r
+            self._configFile.AddPreDefined('MDE_CPU_IA32')\r
+            self._configFile.AddPreDefined('MDE_CPU_X64')\r
+            self._configFile.AddPreDefined('MDE_CPU_IPF')\r
+            self._configFile.AddPreDefined('MDE_CPU_EBC')\r
+            self._configFile.AddPreDefined('MDE_CPU_ARM')\r
+\r
+        for macro in self._macros:\r
+            self._configFile.AddPreDefined(macro)\r
+\r
+        namestr = self._pObj.GetName()\r
+        if self._arch != None:\r
+            namestr += '[%s]' % self._arch\r
+        if self._tooltag != None:\r
+            namestr += '[%s]' % self._tooltag\r
+        self._configFile.SetProjectName(namestr)\r
+        self._configFile.SetStripPath(self._pObj.GetWorkspace())\r
+        self._configFile.SetProjectVersion(self._pObj.GetFileObj().GetVersion())\r
+        self._configFile.AddPattern('*.decdoxygen')\r
+\r
+        if self._tooltag.lower() == 'msft':\r
+            self._configFile.AddPreDefined('_MSC_EXTENSIONS')\r
+        elif self._tooltag.lower() == 'gnu':\r
+            self._configFile.AddPreDefined('__GNUC__')\r
+        elif self._tooltag.lower() == 'intel':\r
+            self._configFile.AddPreDefined('__INTEL_COMPILER')\r
+        else:\r
+            self._tooltag = None\r
+            self._configFile.AddPreDefined('_MSC_EXTENSIONS')\r
+            self._configFile.AddPreDefined('__GNUC__')\r
+            self._configFile.AddPreDefined('__INTEL_COMPILER')\r
+\r
+        self._configFile.AddPreDefined('ASM_PFX= ')\r
+        self._configFile.AddPreDefined('OPTIONAL= ')\r
+\r
+    def GenerateIndexPage(self):\r
+        """Generate doxygen index page. Inherited class should implement it."""\r
+        fObj   = self._pObj.GetFileObj()\r
+        pdObj  = doxygen.DoxygenFile('%s Package Document' % self._pObj.GetName(),\r
+                                     '%s.decdoxygen' % self._pObj.GetFilename())\r
+        self._configFile.AddFile(pdObj.GetFilename())\r
+        pdObj.AddDescription(fObj.GetFileHeader())\r
+\r
+        defSection = fObj.GetSectionByName('defines')[0]\r
+        baseSection = doxygen.Section('PackageBasicInformation', 'Package Basic Information')\r
+        descr = '<TABLE>'\r
+        for obj in defSection.GetObjects():\r
+            if obj.GetKey() in _dec_key_description_mapping_table.keys():\r
+                descr += '<TR>'\r
+                descr += '<TD><B>%s</B></TD>' % _dec_key_description_mapping_table[obj.GetKey()]\r
+                descr += '<TD>%s</TD>' % obj.GetValue()\r
+                descr += '</TR>'\r
+        descr += '</TABLE><br>'\r
+        baseSection.AddDescription(descr)\r
+        pdObj.AddSection(baseSection)\r
+\r
+        knownIssueSection = doxygen.Section('Known_Issue_section', 'Known Issue')\r
+        knownIssueSection.AddDescription('<ul>')\r
+        knownIssueSection.AddDescription('<li> OPTIONAL macro for function parameter can not be dealed with doxygen, so it disapear in this document! </li>')\r
+        knownIssueSection.AddDescription('</ul>')\r
+        pdObj.AddSection(knownIssueSection)\r
+\r
+        self.AddAllIncludeFiles(self._pObj, self._configFile)\r
+        pages = self.GenerateIncludesSubPage(self._pObj, self._configFile)\r
+        if len(pages) != 0:\r
+            pdObj.AddPages(pages)\r
+        pages = self.GenerateLibraryClassesSubPage(self._pObj, self._configFile)\r
+        if len(pages) != 0:\r
+            pdObj.AddPages(pages)\r
+        pages = self.GeneratePcdSubPages(self._pObj, self._configFile)\r
+        if len(pages) != 0:\r
+            pdObj.AddPages(pages)\r
+        pages = self.GenerateGuidSubPages(self._pObj, self._configFile)\r
+        if len(pages) != 0:\r
+            pdObj.AddPages(pages)\r
+        pages = self.GeneratePpiSubPages(self._pObj, self._configFile)\r
+        if len(pages) != 0:\r
+            pdObj.AddPages(pages)\r
+        pages = self.GenerateProtocolSubPages(self._pObj, self._configFile)\r
+        if len(pages) != 0:\r
+            pdObj.AddPages(pages)\r
+        if not self._onlyIncludeDocument:\r
+            pdObj.AddPages(self.GenerateModulePages(self._pObj, self._configFile))\r
+\r
+        pdObj.Save()\r
+        return pdObj.GetFilename()\r
+\r
+    def GenerateIncludesSubPage(self, pObj, configFile):\r
+        # by default add following path as include path to config file\r
+        pkpath = pObj.GetFileObj().GetPackageRootPath()\r
+        configFile.AddIncludePath(os.path.join(pkpath, 'Include'))\r
+        configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Library'))\r
+        configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Protocol'))\r
+        configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Ppi'))\r
+        configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'Guid'))\r
+        configFile.AddIncludePath(os.path.join(pkpath, 'Include', 'IndustryStandard'))\r
+\r
+        rootArray = []\r
+        pageRoot = doxygen.Page("Public Includes", "%s_public_includes" % pObj.GetName())\r
+        objs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+        if len(objs) == 0: return []\r
+\r
+        for obj in objs:\r
+            # Add path to include path\r
+            path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetPath())\r
+            configFile.AddIncludePath(path)\r
+\r
+            # only list common folder's include file\r
+            if obj.GetArch().lower() != 'common':\r
+                continue\r
+\r
+            bNeedAddIncludePage = False\r
+            topPage = doxygen.Page(self._ConvertPathToDoxygen(path, pObj), 'public_include_top')\r
+\r
+            topPage.AddDescription('<ul>\n')\r
+            for file in os.listdir(path):\r
+                if file.lower() in _ignore_dir: continue\r
+                fullpath = os.path.join(path, file)\r
+                if os.path.isfile(fullpath):\r
+                    self.ProcessSourceFileForInclude(fullpath, pObj, configFile)\r
+                    topPage.AddDescription('<li> \link %s\endlink </li>\n' % self._ConvertPathToDoxygen(fullpath, pObj))\r
+                else:\r
+                    if file.lower() in ['library', 'protocol', 'guid', 'ppi', 'ia32', 'x64', 'ipf', 'ebc', 'arm', 'pi', 'uefi', 'aarch64']:\r
+                        continue\r
+                    bNeedAddSubPage = False\r
+                    subpage = doxygen.Page(self._ConvertPathToDoxygen(fullpath, pObj), 'public_include_%s' % file)\r
+                    subpage.AddDescription('<ul>\n')\r
+                    for subfile in os.listdir(fullpath):\r
+                        if subfile.lower() in _ignore_dir: continue\r
+                        bNeedAddSubPage = True\r
+                        subfullpath = os.path.join(fullpath, subfile)\r
+                        self.ProcessSourceFileForInclude(subfullpath, pObj, configFile)\r
+                        subpage.AddDescription('<li> \link %s \endlink </li>\n' % self._ConvertPathToDoxygen(subfullpath, pObj))\r
+                    subpage.AddDescription('</ul>\n')\r
+                    if bNeedAddSubPage:\r
+                        bNeedAddIncludePage = True\r
+                        pageRoot.AddPage(subpage)\r
+            topPage.AddDescription('</ul>\n')\r
+            if bNeedAddIncludePage:\r
+                pageRoot.AddPage(topPage)\r
+\r
+        if pageRoot.GetSubpageCount() != 0:\r
+            return [pageRoot]\r
+        else:\r
+            return []\r
+\r
+    def GenerateLibraryClassesSubPage(self, pObj, configFile):\r
+        """\r
+        Generate sub page for library class for package.\r
+        One DEC file maybe contains many library class sections\r
+        for different architecture.\r
+\r
+        @param  fObj DEC file object.\r
+        """\r
+        rootArray = []\r
+        pageRoot = doxygen.Page("Library Class", "%s_libraryclass" % pObj.GetName())\r
+        objs = pObj.GetFileObj().GetSectionObjectsByName('libraryclass', self._arch)\r
+        if len(objs) == 0: return []\r
+\r
+        if self._arch != None:\r
+            for obj in objs:\r
+                classPage = doxygen.Page(obj.GetClassName(),\r
+                                         "lc_%s" % obj.GetClassName())\r
+                comments = obj.GetComment()\r
+                if len(comments) != 0:\r
+                    classPage.AddDescription('<br>\n'.join(comments) + '<br>\n')\r
+                pageRoot.AddPage(classPage)\r
+                path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+                path = path[len(pObj.GetWorkspace()) + 1:]\r
+                if len(comments) == 0:\r
+                    classPage.AddDescription('\copydoc %s<p>' % obj.GetHeaderFile())\r
+                section = doxygen.Section('ref', 'Refer to Header File')\r
+                section.AddDescription('\link %s\n' % obj.GetHeaderFile())\r
+                section.AddDescription(' \endlink<p>\n')\r
+                classPage.AddSection(section)\r
+                fullPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+                self.ProcessSourceFileForInclude(fullPath, pObj, configFile)\r
+        else:\r
+            archPageDict = {}\r
+            for obj in objs:\r
+                if obj.GetArch() not in archPageDict.keys():\r
+                    archPageDict[obj.GetArch()] = doxygen.Page(obj.GetArch(),\r
+                                                               'lc_%s' % obj.GetArch())\r
+                    pageRoot.AddPage(archPageDict[obj.GetArch()])\r
+                subArchRoot = archPageDict[obj.GetArch()]\r
+                classPage = doxygen.Page(obj.GetClassName(),\r
+                                         "lc_%s" % obj.GetClassName())\r
+                comments = obj.GetComment()\r
+                if len(comments) != 0:\r
+                    classPage.AddDescription('<br>\n'.join(comments) + '<br>\n')\r
+                subArchRoot.AddPage(classPage)\r
+                path = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+                path = path[len(pObj.GetWorkspace()) + 1:]\r
+                if len(comments) == 0:\r
+                    classPage.AddDescription('\copydoc %s<p>' % obj.GetHeaderFile())\r
+                section = doxygen.Section('ref', 'Refer to Header File')\r
+                section.AddDescription('\link %s\n' % obj.GetHeaderFile())\r
+                section.AddDescription(' \endlink<p>\n')\r
+                classPage.AddSection(section)\r
+                fullPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetHeaderFile())\r
+\r
+                self.ProcessSourceFileForInclude(fullPath, pObj, configFile)\r
+        rootArray.append(pageRoot)\r
+        return rootArray\r
+\r
+    def ProcessSourceFileForInclude(self, path, pObj, configFile, infObj=None):\r
+        """\r
+        @param path        the analysising file full path\r
+        @param pObj        package object\r
+        @param configFile  doxygen config file.\r
+        """\r
+\r
+        if gInGui:\r
+            wx.Yield()\r
+        if not os.path.exists(path):\r
+            ErrorMsg('Source file path %s does not exist!' % path)\r
+            return\r
+\r
+        if configFile.FileExists(path):\r
+            return\r
+\r
+        try:\r
+            f = open(path, 'r')\r
+            lines = f.readlines()\r
+            f.close()\r
+        except IOError:\r
+            ErrorMsg('Fail to open file %s' % path)\r
+            return\r
+\r
+        configFile.AddFile(path)\r
+        return\r
+        no = 0\r
+        for no in xrange(len(lines)):\r
+            if len(lines[no].strip()) == 0:\r
+                continue\r
+            if lines[no].strip()[:2] in ['##', '//', '/*', '*/']:\r
+                continue\r
+            index = lines[no].lower().find('include')\r
+            #mo = IncludePattern.finditer(lines[no].lower())\r
+            mo = re.match(r"^#\s*include\s+[<\"]([\\/\w.]+)[>\"]$", lines[no].strip().lower())\r
+            if not mo:\r
+                continue\r
+            mo = re.match(r"^[#\w\s]+[<\"]([\\/\w.]+)[>\"]$", lines[no].strip())\r
+            filePath = mo.groups()[0]\r
+\r
+            if filePath == None or len(filePath) == 0:\r
+                continue\r
+\r
+            # find header file in module's path firstly.\r
+            fullPath = None\r
+\r
+            if os.path.exists(os.path.join(os.path.dirname(path), filePath)):\r
+                # Find the file in current directory\r
+                fullPath = os.path.join(os.path.dirname(path), filePath).replace('\\', '/')\r
+            else:\r
+                # find in depedent package's include path\r
+                incObjs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+                for incObj in incObjs:\r
+                    incPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), incObj.GetPath()).strip()\r
+                    incPath = os.path.realpath(os.path.join(incPath, filePath))\r
+                    if os.path.exists(incPath):\r
+                        fullPath = incPath\r
+                        break\r
+                if infObj != None:\r
+                    pkgInfObjs = infObj.GetSectionObjectsByName('packages')\r
+                    for obj in  pkgInfObjs:\r
+                        decObj = dec.DECFile(os.path.join(pObj.GetWorkspace(), obj.GetPath()))\r
+                        if not decObj:\r
+                            ErrorMsg ('Fail to create pacakge object for %s' % obj.GetPackageName())\r
+                            continue\r
+                        if not decObj.Parse():\r
+                            ErrorMsg ('Fail to load package object for %s' % obj.GetPackageName())\r
+                            continue\r
+                        incObjs = decObj.GetSectionObjectsByName('includes')\r
+                        for incObj in incObjs:\r
+                            incPath = os.path.join(decObj.GetPackageRootPath(), incObj.GetPath()).replace('\\', '/')\r
+                            if os.path.exists(os.path.join(incPath, filePath)):\r
+                                fullPath = os.path.join(os.path.join(incPath, filePath))\r
+                                break\r
+                        if fullPath != None:\r
+                            break\r
+\r
+            if fullPath == None and self.IsVerbose():\r
+                self.Log('Can not resolve header file %s for file %s in package %s\n' % (filePath, path, pObj.GetFileObj().GetFilename()), 'error')\r
+                return\r
+            else:\r
+                fullPath = fullPath.replace('\\', '/')\r
+                if self.IsVerbose():\r
+                    self.Log('Preprocessing: Add include file %s for file %s\n' % (fullPath, path))\r
+                #LogMsg ('Preprocessing: Add include file %s for file %s' % (fullPath, path))\r
+                self.ProcessSourceFileForInclude(fullPath, pObj, configFile, infObj)\r
+\r
+    def AddAllIncludeFiles(self, pObj, configFile):\r
+        objs = pObj.GetFileObj().GetSectionObjectsByName('includes')\r
+        for obj in objs:\r
+            incPath = os.path.join(pObj.GetFileObj().GetPackageRootPath(), obj.GetPath())\r
+            for root, dirs, files in os.walk(incPath):\r
+                for dir in dirs:\r
+                    if dir.lower() in _ignore_dir:\r
+                        dirs.remove(dir)\r
+                for file in files:\r
+                    path = os.path.normpath(os.path.join(root, file))\r
+                    configFile.AddFile(path.replace('/', '\\'))\r
+\r
+    def GeneratePcdSubPages(self, pObj, configFile):\r
+        """\r
+        Generate sub pages for package's PCD definition.\r
+        @param pObj         package object\r
+        @param configFile   config file object\r
+        """\r
+        rootArray = []\r
+        objs = pObj.GetFileObj().GetSectionObjectsByName('pcd')\r
+        if len(objs) == 0:\r
+            return []\r
+\r
+        pcdRootPage = doxygen.Page('PCD', 'pcd_root_page')\r
+        typeRootPageDict = {}\r
+        typeArchRootPageDict = {}\r
+        for obj in objs:\r
+            if obj.GetPcdType() not in typeRootPageDict.keys():\r
+                typeRootPageDict[obj.GetPcdType()] = doxygen.Page(obj.GetPcdType(), 'pcd_%s_root_page' % obj.GetPcdType())\r
+                pcdRootPage.AddPage(typeRootPageDict[obj.GetPcdType()])\r
+            typeRoot = typeRootPageDict[obj.GetPcdType()]\r
+            if self._arch != None:\r
+                pcdPage = doxygen.Page('%s' % obj.GetPcdName(),\r
+                                        'pcd_%s_%s_%s' % (obj.GetPcdType(), obj.GetArch(), obj.GetPcdName().split('.')[1]))\r
+                pcdPage.AddDescription('<br>\n'.join(obj.GetComment()) + '<br>\n')\r
+                section = doxygen.Section('PCDinformation', 'PCD Information')\r
+                desc  = '<TABLE>'\r
+                desc += '<TR>'\r
+                desc += '<TD><CAPTION>Name</CAPTION></TD>'\r
+                desc += '<TD><CAPTION>Token Space</CAPTION></TD>'\r
+                desc += '<TD><CAPTION>Token number</CAPTION></TD>'\r
+                desc += '<TD><CAPTION>Data Type</CAPTION></TD>'\r
+                desc += '<TD><CAPTION>Default Value</CAPTION></TD>'\r
+                desc += '</TR>'\r
+                desc += '<TR>'\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[1]\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[0]\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdToken()\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdDataType()\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdValue()\r
+                desc += '</TR>'\r
+                desc += '</TABLE>'\r
+                section.AddDescription(desc)\r
+                pcdPage.AddSection(section)\r
+                typeRoot.AddPage(pcdPage)\r
+            else:\r
+                keystr = obj.GetPcdType() + obj.GetArch()\r
+                if keystr not in typeArchRootPageDict.keys():\r
+                    typeArchRootPage = doxygen.Page(obj.GetArch(), 'pcd_%s_%s_root_page' % (obj.GetPcdType(), obj.GetArch()))\r
+                    typeArchRootPageDict[keystr] = typeArchRootPage\r
+                    typeRoot.AddPage(typeArchRootPage)\r
+                typeArchRoot = typeArchRootPageDict[keystr]\r
+                pcdPage = doxygen.Page('%s' % obj.GetPcdName(),\r
+                                        'pcd_%s_%s_%s' % (obj.GetPcdType(), obj.GetArch(), obj.GetPcdName().split('.')[1]))\r
+                pcdPage.AddDescription('<br>\n'.join(obj.GetComment()) + '<br>\n')\r
+                section = doxygen.Section('PCDinformation', 'PCD Information')\r
+                desc  = '<TABLE>'\r
+                desc += '<TR>'\r
+                desc += '<TD><CAPTION>Name</CAPTION></TD>'\r
+                desc += '<TD><CAPTION>Token Space</CAPTION></TD>'\r
+                desc += '<TD><CAPTION>Token number</CAPTION></TD>'\r
+                desc += '<TD><CAPTION>Data Type</CAPTION></TD>'\r
+                desc += '<TD><CAPTION>Default Value</CAPTION></TD>'\r
+                desc += '</TR>'\r
+                desc += '<TR>'\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[1]\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdName().split('.')[0]\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdToken()\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdDataType()\r
+                desc += '<TD><CAPTION>%s</CAPTION></TD>' % obj.GetPcdValue()\r
+                desc += '</TR>'\r
+                desc += '</TABLE>'\r
+                section.AddDescription(desc)\r
+                pcdPage.AddSection(section)\r
+                typeArchRoot.AddPage(pcdPage)\r
+        return [pcdRootPage]\r
+\r
+    def _GenerateGuidSubPage(self, pObj, obj, configFile):\r
+        guidPage = doxygen.Page('%s' % obj.GetName(),\r
+                                'guid_%s_%s' % (obj.GetArch(), obj.GetName()))\r
+        comments = obj.GetComment()\r
+        if len(comments) != 0:\r
+            guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+        section = doxygen.Section('BasicGuidInfo', 'GUID Information')\r
+        desc  = '<TABLE>'\r
+        desc += '<TR>'\r
+        desc += '<TD><CAPTION>GUID\'s Guid Name</CAPTION></TD><TD><CAPTION>GUID\'s Guid</CAPTION></TD>'\r
+        desc += '</TR>'\r
+        desc += '<TR>'\r
+        desc += '<TD>%s</TD>' % obj.GetName()\r
+        desc += '<TD>%s</TD>' % obj.GetGuid()\r
+        desc += '</TR>'\r
+        desc += '</TABLE>'\r
+        section.AddDescription(desc)\r
+        guidPage.AddSection(section)\r
+        refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+        if refFile:\r
+            relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+            if len(comments) == 0:\r
+                guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+\r
+            section = doxygen.Section('ref', 'Refer to Header File')\r
+            section.AddDescription('\link %s\n' % relPath)\r
+            section.AddDescription('\endlink\n')\r
+            self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+            guidPage.AddSection(section)\r
+        return guidPage\r
+\r
+    def GenerateGuidSubPages(self, pObj, configFile):\r
+        """\r
+        Generate sub pages for package's GUID definition.\r
+        @param  pObj            package object\r
+        @param  configFilf      doxygen config file object\r
+        """\r
+        pageRoot = doxygen.Page('GUID', 'guid_root_page')\r
+        objs = pObj.GetFileObj().GetSectionObjectsByName('guids', self._arch)\r
+        if len(objs) == 0: return []\r
+        if self._arch != None:\r
+            for obj in objs:\r
+                pageRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, configFile))\r
+        else:\r
+            guidArchRootPageDict = {}\r
+            for obj in objs:\r
+                if obj.GetArch() not in guidArchRootPageDict.keys():\r
+                    guidArchRoot = doxygen.Page(obj.GetArch(), 'guid_arch_root_%s' % obj.GetArch())\r
+                    pageRoot.AddPage(guidArchRoot)\r
+                    guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+                guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+                guidArchRoot.AddPage(self._GenerateGuidSubPage(pObj, obj, configFile))\r
+        return [pageRoot]\r
+\r
+    def _GeneratePpiSubPage(self, pObj, obj, configFile):\r
+        guidPage = doxygen.Page(obj.GetName(), 'ppi_page_%s' % obj.GetName())\r
+        comments = obj.GetComment()\r
+        if len(comments) != 0:\r
+            guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+        section = doxygen.Section('BasicPpiInfo', 'PPI Information')\r
+        desc  = '<TABLE>'\r
+        desc += '<TR>'\r
+        desc += '<TD><CAPTION>PPI\'s Guid Name</CAPTION></TD><TD><CAPTION>PPI\'s Guid</CAPTION></TD>'\r
+        desc += '</TR>'\r
+        desc += '<TR>'\r
+        desc += '<TD>%s</TD>' % obj.GetName()\r
+        desc += '<TD>%s</TD>' % obj.GetGuid()\r
+        desc += '</TR>'\r
+        desc += '</TABLE>'\r
+        section.AddDescription(desc)\r
+        guidPage.AddSection(section)\r
+        refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+        if refFile:\r
+            relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+            if len(comments) == 0:\r
+                guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+            section = doxygen.Section('ref', 'Refer to Header File')\r
+            section.AddDescription('\link %s\n' % relPath)\r
+            section.AddDescription('\endlink\n')\r
+            self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+            guidPage.AddSection(section)\r
+\r
+        return guidPage\r
+\r
+    def GeneratePpiSubPages(self, pObj, configFile):\r
+        """\r
+        Generate sub pages for package's GUID definition.\r
+        @param  pObj            package object\r
+        @param  configFilf      doxygen config file object\r
+        """\r
+        pageRoot = doxygen.Page('PPI', 'ppi_root_page')\r
+        objs = pObj.GetFileObj().GetSectionObjectsByName('ppis', self._arch)\r
+        if len(objs) == 0: return []\r
+        if self._arch != None:\r
+            for obj in objs:\r
+                pageRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, configFile))\r
+        else:\r
+            guidArchRootPageDict = {}\r
+            for obj in objs:\r
+                if obj.GetArch() not in guidArchRootPageDict.keys():\r
+                    guidArchRoot = doxygen.Page(obj.GetArch(), 'ppi_arch_root_%s' % obj.GetArch())\r
+                    pageRoot.AddPage(guidArchRoot)\r
+                    guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+                guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+                guidArchRoot.AddPage(self._GeneratePpiSubPage(pObj, obj, configFile))\r
+        return [pageRoot]\r
+\r
+    def _GenerateProtocolSubPage(self, pObj, obj, configFile):\r
+        guidPage = doxygen.Page(obj.GetName(), 'protocol_page_%s' % obj.GetName())\r
+        comments = obj.GetComment()\r
+        if len(comments) != 0:\r
+            guidPage.AddDescription('<br>'.join(obj.GetComment()) + '<br>')\r
+        section = doxygen.Section('BasicProtocolInfo', 'PROTOCOL Information')\r
+        desc  = '<TABLE>'\r
+        desc += '<TR>'\r
+        desc += '<TD><CAPTION>PROTOCOL\'s Guid Name</CAPTION></TD><TD><CAPTION>PROTOCOL\'s Guid</CAPTION></TD>'\r
+        desc += '</TR>'\r
+        desc += '<TR>'\r
+        desc += '<TD>%s</TD>' % obj.GetName()\r
+        desc += '<TD>%s</TD>' % obj.GetGuid()\r
+        desc += '</TR>'\r
+        desc += '</TABLE>'\r
+        section.AddDescription(desc)\r
+        guidPage.AddSection(section)\r
+\r
+        refFile = self.FindHeaderFileForGuid(pObj, obj.GetName(), configFile)\r
+        if refFile:\r
+            relPath = refFile[len(pObj.GetWorkspace()) + 1:]\r
+            if len(comments) == 0:\r
+                guidPage.AddDescription(' \\copydoc %s <br>' % relPath)\r
+            section = doxygen.Section('ref', 'Refer to Header File')\r
+            section.AddDescription('\link %s\n' % relPath)\r
+            section.AddDescription('\endlink\n')\r
+            self.ProcessSourceFileForInclude(refFile, pObj, configFile)\r
+            guidPage.AddSection(section)\r
+\r
+        return guidPage\r
+\r
+    def GenerateProtocolSubPages(self, pObj, configFile):\r
+        """\r
+        Generate sub pages for package's GUID definition.\r
+        @param  pObj            package object\r
+        @param  configFilf      doxygen config file object\r
+        """\r
+        pageRoot = doxygen.Page('PROTOCOL', 'protocol_root_page')\r
+        objs = pObj.GetFileObj().GetSectionObjectsByName('protocols', self._arch)\r
+        if len(objs) == 0: return []\r
+        if self._arch != None:\r
+            for obj in objs:\r
+                pageRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, configFile))\r
+        else:\r
+            guidArchRootPageDict = {}\r
+            for obj in objs:\r
+                if obj.GetArch() not in guidArchRootPageDict.keys():\r
+                    guidArchRoot = doxygen.Page(obj.GetArch(), 'protocol_arch_root_%s' % obj.GetArch())\r
+                    pageRoot.AddPage(guidArchRoot)\r
+                    guidArchRootPageDict[obj.GetArch()] = guidArchRoot\r
+                guidArchRoot = guidArchRootPageDict[obj.GetArch()]\r
+                guidArchRoot.AddPage(self._GenerateProtocolSubPage(pObj, obj, configFile))\r
+        return [pageRoot]\r
+\r
+    def FindHeaderFileForGuid(self, pObj, name, configFile):\r
+        """\r
+        For declaration header file for GUID/PPI/Protocol.\r
+\r
+        @param pObj         package object\r
+        @param name         guid/ppi/protocol's name\r
+        @param configFile   config file object\r
+\r
+        @return full path of header file and None if not found.\r
+        """\r
+        startPath  = pObj.GetFileObj().GetPackageRootPath()\r
+        incPath    = os.path.join(startPath, 'Include').replace('\\', '/')\r
+        # if <PackagePath>/include exist, then search header under it.\r
+        if os.path.exists(incPath):\r
+            startPath = incPath\r
+\r
+        for root, dirs, files in os.walk(startPath):\r
+            for dir in dirs:\r
+                if dir.lower() in _ignore_dir:\r
+                    dirs.remove(dir)\r
+            for file in files:\r
+                fPath = os.path.join(root, file)\r
+                if not IsCHeaderFile(fPath):\r
+                    continue\r
+                try:\r
+                    f = open(fPath, 'r')\r
+                    lines = f.readlines()\r
+                    f.close()\r
+                except IOError:\r
+                    self.Log('Fail to open file %s\n' % fPath)\r
+                    continue\r
+                for line in lines:\r
+                    if line.find(name) != -1 and \\r
+                       line.find('extern') != -1:\r
+                        return fPath.replace('\\', '/')\r
+        return None\r
+\r
+    def GetPackageModuleList(self, pObj):\r
+        """\r
+        Get all module's INF path under package's root path\r
+        @param     pObj  package object\r
+        @return    arrary of INF full path\r
+        """\r
+        mArray = []\r
+        packPath = pObj.GetFileObj().GetPackageRootPath()\r
+        if not os.path.exists:\r
+            return None\r
+        for root, dirs, files in os.walk(packPath):\r
+            for dir in dirs:\r
+                if dir.lower() in _ignore_dir:\r
+                    dirs.remove(dir)\r
+            for file in files:\r
+                if CheckPathPostfix(file, 'inf'):\r
+                    fPath = os.path.join(root, file).replace('\\', '/')\r
+                    mArray.append(fPath)\r
+        return mArray\r
+\r
+    def GenerateModulePages(self, pObj, configFile):\r
+        """\r
+        Generate sub pages for package's module which is under the package\r
+        root directory.\r
+\r
+        @param  pObj            package object\r
+        @param  configFilf      doxygen config file object\r
+        """\r
+        infList = self.GetPackageModuleList(pObj)\r
+        rootPages = []\r
+        libObjs = []\r
+        modObjs = []\r
+        for infpath in infList:\r
+            infObj = inf.INFFile(infpath)\r
+            #infObj = INFFileObject.INFFile (pObj.GetWorkspacePath(),\r
+            #                                inf)\r
+            if not infObj:\r
+                self.Log('Fail create INF object for %s' % inf)\r
+                continue\r
+            if not infObj.Parse():\r
+                self.Log('Fail to load INF file %s' % inf)\r
+                continue\r
+            if infObj.GetProduceLibraryClass() != None:\r
+                libObjs.append(infObj)\r
+            else:\r
+                modObjs.append(infObj)\r
+\r
+        if len(libObjs) != 0:\r
+            libRootPage = doxygen.Page('Libraries', 'lib_root_page')\r
+            rootPages.append(libRootPage)\r
+            for libInf in libObjs:\r
+                libRootPage.AddPage(self.GenerateModulePage(pObj, libInf, configFile, True))\r
+\r
+        if len(modObjs) != 0:\r
+            modRootPage = doxygen.Page('Modules', 'module_root_page')\r
+            rootPages.append(modRootPage)\r
+            for modInf in modObjs:\r
+                modRootPage.AddPage(self.GenerateModulePage(pObj, modInf, configFile, False))\r
+\r
+        return rootPages\r
+\r
+    def GenerateModulePage(self, pObj, infObj, configFile, isLib):\r
+        """\r
+        Generate page for a module/library.\r
+        @param infObj     INF file object for module/library\r
+        @param configFile doxygen config file object\r
+        @param isLib      Whether this module is libary\r
+\r
+        @param module doxygen page object\r
+        """\r
+        workspace = pObj.GetWorkspace()\r
+        refDecObjs = []\r
+        for obj in  infObj.GetSectionObjectsByName('packages'):\r
+            decObj = dec.DECFile(os.path.join(workspace, obj.GetPath()))\r
+            if not decObj:\r
+                ErrorMsg ('Fail to create pacakge object for %s' % obj.GetPackageName())\r
+                continue\r
+            if not decObj.Parse():\r
+                ErrorMsg ('Fail to load package object for %s' % obj.GetPackageName())\r
+                continue\r
+            refDecObjs.append(decObj)\r
+\r
+        modPage = doxygen.Page('%s' % infObj.GetBaseName(),\r
+                               'module_%s' % infObj.GetBaseName())\r
+        modPage.AddDescription(infObj.GetFileHeader())\r
+\r
+        basicInfSection = doxygen.Section('BasicModuleInformation', 'Basic Module Information')\r
+        desc = "<TABLE>"\r
+        for obj in infObj.GetSectionObjectsByName('defines'):\r
+            key = obj.GetKey()\r
+            value = obj.GetValue()\r
+            if key not in _inf_key_description_mapping_table.keys(): continue\r
+            if key == 'LIBRARY_CLASS' and value.find('|') != -1:\r
+                clsname, types = value.split('|')\r
+                desc += '<TR>'\r
+                desc += '<TD><B>%s</B></TD>' % _inf_key_description_mapping_table[key]\r
+                desc += '<TD>%s</TD>' % clsname\r
+                desc += '</TR>'\r
+\r
+                desc += '<TR>'\r
+                desc += '<TD><B>Supported Module Types</B></TD>'\r
+                desc += '<TD>%s</TD>' % types\r
+                desc += '</TR>'\r
+            else:\r
+                desc += '<TR>'\r
+                desc += '<TD><B>%s</B></TD>' % _inf_key_description_mapping_table[key]\r
+                if key == 'EFI_SPECIFICATION_VERSION' and value == '0x00020000':\r
+                    value = '2.0'\r
+                desc += '<TD>%s</TD>' % value\r
+                desc += '</TR>'\r
+        desc += '</TABLE>'\r
+        basicInfSection.AddDescription(desc)\r
+        modPage.AddSection(basicInfSection)\r
+\r
+        # Add protocol section\r
+        data  = []\r
+        for obj in infObj.GetSectionObjectsByName('pcd', self._arch):\r
+            data.append(obj.GetPcdName().strip())\r
+        if len(data) != 0:\r
+            s = doxygen.Section('Pcds', 'Pcds')\r
+            desc = "<TABLE>"\r
+            desc += '<TR><TD><B>PCD Name</B></TD><TD><B>TokenSpace</B></TD><TD><B>Package</B></TD></TR>'\r
+            for item in data:\r
+                desc += '<TR>'\r
+                desc += '<TD>%s</TD>' % item.split('.')[1]\r
+                desc += '<TD>%s</TD>' % item.split('.')[0]\r
+                pkgbasename = self.SearchPcdPackage(item, workspace, refDecObjs)\r
+                desc += '<TD>%s</TD>' % pkgbasename\r
+                desc += '</TR>'\r
+            desc += "</TABLE>"\r
+            s.AddDescription(desc)\r
+            modPage.AddSection(s)\r
+\r
+        # Add protocol section\r
+        #sects = infObj.GetSectionByString('protocol')\r
+        data  = []\r
+        #for sect in sects:\r
+        for obj in infObj.GetSectionObjectsByName('protocol', self._arch):\r
+            data.append(obj.GetName().strip())\r
+        if len(data) != 0:\r
+            s = doxygen.Section('Protocols', 'Protocols')\r
+            desc = "<TABLE>"\r
+            desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+            for item in data:\r
+                desc += '<TR>'\r
+                desc += '<TD>%s</TD>' % item\r
+                pkgbasename = self.SearchProtocolPackage(item, workspace, refDecObjs)\r
+                desc += '<TD>%s</TD>' % pkgbasename\r
+                desc += '</TR>'\r
+            desc += "</TABLE>"\r
+            s.AddDescription(desc)\r
+            modPage.AddSection(s)\r
+\r
+        # Add ppi section\r
+        #sects = infObj.GetSectionByString('ppi')\r
+        data  = []\r
+        #for sect in sects:\r
+        for obj in infObj.GetSectionObjectsByName('ppi', self._arch):\r
+            data.append(obj.GetName().strip())\r
+        if len(data) != 0:\r
+            s = doxygen.Section('Ppis', 'Ppis')\r
+            desc = "<TABLE>"\r
+            desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+            for item in data:\r
+                desc += '<TR>'\r
+                desc += '<TD>%s</TD>' % item\r
+                pkgbasename = self.SearchPpiPackage(item, workspace, refDecObjs)\r
+                desc += '<TD>%s</TD>' % pkgbasename\r
+                desc += '</TR>'\r
+            desc += "</TABLE>"\r
+            s.AddDescription(desc)\r
+            modPage.AddSection(s)\r
+\r
+        # Add guid section\r
+        #sects = infObj.GetSectionByString('guid')\r
+        data  = []\r
+        #for sect in sects:\r
+        for obj in infObj.GetSectionObjectsByName('guid', self._arch):\r
+            data.append(obj.GetName().strip())\r
+        if len(data) != 0:\r
+            s = doxygen.Section('Guids', 'Guids')\r
+            desc = "<TABLE>"\r
+            desc += '<TR><TD><B>Name</B></TD><TD><B>Package</B></TD></TR>'\r
+            for item in data:\r
+                desc += '<TR>'\r
+                desc += '<TD>%s</TD>' % item\r
+                pkgbasename = self.SearchGuidPackage(item, workspace, refDecObjs)\r
+                desc += '<TD>%s</TD>' % pkgbasename\r
+                desc += '</TR>'\r
+            desc += "</TABLE>"\r
+            s.AddDescription(desc)\r
+            modPage.AddSection(s)\r
+\r
+        section = doxygen.Section('LibraryClasses', 'Library Classes')\r
+        desc = "<TABLE>"\r
+        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
+        if isLib:\r
+            desc += '<TR>'\r
+            desc += '<TD>%s</TD>' % infObj.GetProduceLibraryClass()\r
+            desc += '<TD>Produce</TD>'\r
+            try:\r
+                pkgname, hPath = self.SearchLibraryClassHeaderFile(infObj.GetProduceLibraryClass(),\r
+                                                              workspace,\r
+                                                              refDecObjs)\r
+            except:\r
+                self.Log ('fail to get package header file for lib class %s' % infObj.GetProduceLibraryClass())\r
+                pkgname = 'NULL'\r
+                hPath   = 'NULL'\r
+            desc += '<TD>%s</TD>' % pkgname\r
+            if hPath != "NULL":\r
+                #desc += '<TD>\link %s \endlink</TD>' % hPath\r
+                desc += '<TD>%s</TD>' % hPath\r
+            else:\r
+                desc += '<TD>%s</TD>' % hPath\r
+            desc += '</TR>'\r
+        for lcObj in infObj.GetSectionObjectsByName('libraryclasses', self._arch):\r
+            desc += '<TR>'\r
+            desc += '<TD>%s</TD>' % lcObj.GetClass()\r
+            retarr = self.SearchLibraryClassHeaderFile(lcObj.GetClass(),\r
+                                                       workspace,\r
+                                                       refDecObjs)\r
+            if retarr != None:\r
+                pkgname, hPath = retarr\r
+            else:\r
+                self.Log('Fail find the library class %s definition from module %s dependent package!' % (lcObj.GetClass(), infObj.GetFilename()), 'error')\r
+                pkgname = 'NULL'\r
+                hPath   = 'NULL'\r
+            desc += '<TD>Consume</TD>'\r
+            desc += '<TD>%s</TD>' % pkgname\r
+            desc += '<TD>%s</TD>' % hPath\r
+            desc += '</TR>'\r
+        desc += "</TABLE>"\r
+        section.AddDescription(desc)\r
+        modPage.AddSection(section)\r
+\r
+        section = doxygen.Section('SourceFiles', 'Source Files')\r
+        section.AddDescription('<ul>\n')\r
+        for obj in infObj.GetSourceObjects(self._arch, self._tooltag):\r
+            sPath = infObj.GetModuleRootPath()\r
+            sPath = os.path.join(sPath, obj.GetSourcePath()).replace('\\', '/').strip()\r
+            if sPath.lower().endswith('.uni') or sPath.lower().endswith('.s') or sPath.lower().endswith('.asm') or sPath.lower().endswith('.nasm'):\r
+                newPath = self.TranslateUniFile(sPath)\r
+                configFile.AddFile(newPath)\r
+                newPath = newPath[len(pObj.GetWorkspace()) + 1:]\r
+                section.AddDescription('<li> \link %s \endlink </li>' %  newPath)\r
+            else:\r
+                self.ProcessSourceFileForInclude(sPath, pObj, configFile, infObj)\r
+                sPath = sPath[len(pObj.GetWorkspace()) + 1:]\r
+                section.AddDescription('<li>\link %s \endlink </li>' % sPath)\r
+        section.AddDescription('</ul>\n')\r
+        modPage.AddSection(section)\r
+\r
+        #sects = infObj.GetSectionByString('depex')\r
+        data  = []\r
+        #for sect in sects:\r
+        for obj in infObj.GetSectionObjectsByName('depex'):\r
+            data.append(str(obj))\r
+        if len(data) != 0:\r
+            s = doxygen.Section('DependentSection', 'Module Dependencies')\r
+            s.AddDescription('<br>'.join(data))\r
+            modPage.AddSection(s)\r
+\r
+        return modPage\r
+\r
+    def TranslateUniFile(self, path):\r
+        newpath = path + '.dox'\r
+        #import core.textfile as textfile\r
+        #file = textfile.TextFile(path)\r
+\r
+        try:\r
+            file = open(path, 'rb')\r
+        except (IOError, OSError), msg:\r
+            return None\r
+\r
+        t = file.read()\r
+        file.close()\r
+\r
+        output = '/** @file \n'\r
+        #output = '<html><body>'\r
+        arr = t.split('\r\n')\r
+        for line in arr:\r
+            if line.find('@file') != -1:\r
+                continue\r
+            if line.find('*/') != -1:\r
+                continue\r
+            line = line.strip()\r
+            if line.strip().startswith('/'):\r
+                arr = line.split(' ')\r
+                if len(arr) > 1:\r
+                    line = ' '.join(arr[1:])\r
+                else:\r
+                    continue\r
+            output += '%s<br>\n' % line\r
+        output += '**/'\r
+\r
+        if os.path.exists(newpath):\r
+            os.remove(newpath)\r
+\r
+        file = open(newpath, "w")\r
+        file.write(output)\r
+        file.close()\r
+        return newpath\r
+\r
+    def SearchPcdPackage(self, pcdname, workspace, decObjs):\r
+        for decObj in  decObjs:\r
+            for pcd in decObj.GetSectionObjectsByName('pcd'):\r
+                if pcdname == pcd.GetPcdName():\r
+                    return decObj.GetBaseName()\r
+        return None\r
+\r
+    def SearchProtocolPackage(self, protname, workspace, decObjs):\r
+        for decObj in  decObjs:\r
+            for proto in decObj.GetSectionObjectsByName('protocol'):\r
+                if protname == proto.GetName():\r
+                    return decObj.GetBaseName()\r
+        return None\r
+\r
+    def SearchPpiPackage(self, ppiname, workspace, decObjs):\r
+        for decObj in  decObjs:\r
+            for ppi in decObj.GetSectionObjectsByName('ppi'):\r
+                if ppiname == ppi.GetName():\r
+                    return decObj.GetBaseName()\r
+        return None\r
+\r
+    def SearchGuidPackage(self, guidname, workspace, decObjs):\r
+        for decObj in  decObjs:\r
+            for guid in decObj.GetSectionObjectsByName('guid'):\r
+                if guidname == guid.GetName():\r
+                    return decObj.GetBaseName()\r
+        return None\r
+\r
+    def SearchLibraryClassHeaderFile(self, className, workspace, decObjs):\r
+        for decObj in  decObjs:\r
+            for cls in decObj.GetSectionObjectsByName('libraryclasses'):\r
+                if cls.GetClassName().strip() == className:\r
+                    path = cls.GetHeaderFile().strip()\r
+                    path = os.path.join(decObj.GetPackageRootPath(), path)\r
+                    path = path[len(workspace) + 1:]\r
+                    return decObj.GetBaseName(), path.replace('\\', '/')\r
+\r
+        return None\r
+\r
+    def _ConvertPathToDoxygen(self, path, pObj):\r
+        pRootPath = pObj.GetWorkspace()\r
+        path = path[len(pRootPath) + 1:]\r
+        return path.replace('\\', '/')\r
+\r
+def IsCHeaderFile(path):\r
+    return CheckPathPostfix(path, 'h')\r
+\r
+def CheckPathPostfix(path, str):\r
+    index = path.rfind('.')\r
+    if index == -1:\r
+        return False\r
+    if path[index + 1:].lower() == str.lower():\r
+        return True\r
+    return False\r