]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/UPT/Library/Parsing.py
BaseTools: Use absolute import in UPT
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Library / Parsing.py
index 95c51406b22a1c2a7dfabeb48c95974103ad1cd3..81729d6cdbf7b3a2c43e6bfaf6072117e128296d 100644 (file)
@@ -1,12 +1,12 @@
 ## @file\r
-# This file is used to define common parsing related functions used in parsing \r
+# This file is used to define common parsing related functions used in parsing\r
 # INF/DEC/DSC process\r
 #\r
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\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
+# 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
@@ -16,6 +16,7 @@
 '''\r
 Parsing\r
 '''\r
+from __future__ import absolute_import\r
 \r
 ##\r
 # Import Modules\r
@@ -23,12 +24,12 @@ Parsing
 import os.path\r
 import re\r
 \r
-from Library.String import RaiseParserError\r
-from Library.String import GetSplitValueList\r
-from Library.String import CheckFileType\r
-from Library.String import CheckFileExist\r
-from Library.String import CleanString\r
-from Library.String import NormPath\r
+from Library.StringUtils import RaiseParserError\r
+from Library.StringUtils import GetSplitValueList\r
+from Library.StringUtils import CheckFileType\r
+from Library.StringUtils import CheckFileExist\r
+from Library.StringUtils import CleanString\r
+from Library.StringUtils import NormPath\r
 \r
 from Logger.ToolError import FILE_NOT_FOUND\r
 from Logger.ToolError import FatalError\r
@@ -42,6 +43,7 @@ from Logger import StringTable as ST
 import Logger.Log as Logger\r
 \r
 from Parser.DecParser import Dec\r
+from . import GlobalData\r
 \r
 gPKG_INFO_DICT = {}\r
 \r
@@ -53,7 +55,7 @@ gPKG_INFO_DICT = {}
 # @param String:  String with BuildOption statement\r
 # @param File:    The file which defines build option, used in error report\r
 #\r
-def GetBuildOption(String, File, LineNo=-1):\r
+def GetBuildOption(String, File, LineNo= -1):\r
     (Family, ToolChain, Flag) = ('', '', '')\r
     if String.find(DataType.TAB_EQUAL_SPLIT) < 0:\r
         RaiseParserError(String, 'BuildOptions', File, \\r
@@ -73,10 +75,10 @@ def GetBuildOption(String, File, LineNo=-1):
 # Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>\r
 #\r
 # @param Item:           String as <LibraryClassKeyWord>|<LibraryInstance>\r
-# @param ContainerFile:  The file which describes the library class, used for \r
+# @param ContainerFile:  The file which describes the library class, used for\r
 #                        error report\r
 #\r
-def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo=-1):\r
+def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1):\r
     List = GetSplitValueList(Item[0])\r
     SupMod = DataType.SUP_MODULE_LIST_STRING\r
     if len(List) != 2:\r
@@ -98,10 +100,10 @@ def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo=-1):
 # [|<TokenSpaceGuidCName>.<PcdCName>]\r
 #\r
 # @param Item:           String as <LibraryClassKeyWord>|<LibraryInstance>\r
-# @param ContainerFile:  The file which describes the library class, used for \r
+# @param ContainerFile:  The file which describes the library class, used for\r
 #                        error report\r
 #\r
-def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo = -1):\r
+def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo= -1):\r
     ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2))\r
     SupMod = DataType.SUP_MODULE_LIST_STRING\r
 \r
@@ -131,9 +133,9 @@ def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo = -1):
 # @param Section:          Used for error report\r
 # @param File:             Used for error report\r
 #\r
-def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo=-1):\r
+def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo= -1):\r
     Format = '<TokenSpaceGuidCName>.<PcdCName>'\r
-    if TokenInfoString != '' and TokenInfoString != None:\r
+    if TokenInfoString != '' and TokenInfoString is not None:\r
         TokenInfoList = GetSplitValueList(TokenInfoString, DataType.TAB_SPLIT)\r
         if len(TokenInfoList) == 2:\r
             return True\r
@@ -147,11 +149,11 @@ def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo=-1):
 #\r
 # @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|\r
 #                        <Value>[|<Type>|<MaximumDatumSize>]\r
-# @param ContainerFile:  The file which describes the pcd, used for error \r
+# @param ContainerFile:  The file which describes the pcd, used for error\r
 #                        report\r
 \r
 #\r
-def GetPcd(Item, Type, ContainerFile, LineNo=-1):\r
+def GetPcd(Item, Type, ContainerFile, LineNo= -1):\r
     TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', ''\r
     List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)\r
 \r
@@ -175,10 +177,10 @@ def GetPcd(Item, Type, ContainerFile, LineNo=-1):
 #\r
 # @param Item:           String as <PcdTokenSpaceGuidCName>\r
 #                        .<TokenCName>|TRUE/FALSE\r
-# @param ContainerFile:  The file which describes the pcd, used for error \r
+# @param ContainerFile:  The file which describes the pcd, used for error\r
 #                        report\r
 #\r
-def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo=-1):\r
+def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo= -1):\r
     TokenGuid, TokenName, Value = '', '', ''\r
     List = GetSplitValueList(Item)\r
     if len(List) != 2:\r
@@ -199,10 +201,10 @@ def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo=-1):
 #\r
 # @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|\r
 #                        TRUE/FALSE\r
-# @param ContainerFile:  The file which describes the pcd, used for error \r
+# @param ContainerFile:  The file which describes the pcd, used for error\r
 #                        report\r
 #\r
-def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo=-1):\r
+def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo= -1):\r
     TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', ''\r
     List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)\r
     if len(List) < 4 or len(List) > 8:\r
@@ -225,10 +227,10 @@ def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo=-1):
 #\r
 # @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|\r
 #                        TRUE/FALSE\r
-# @param ContainerFile:  The file which describes the pcd, used for error \r
+# @param ContainerFile:  The file which describes the pcd, used for error\r
 #                        report\r
 #\r
-def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo = -1):\r
+def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo= -1):\r
     TokenGuid, TokenName, List1, List2, List3, List4, List5 = \\r
     '', '', '', '', '', '', ''\r
     List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)\r
@@ -252,10 +254,10 @@ def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo = -1):
 #\r
 # @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>\r
 #                        |TRUE/FALSE\r
-# @param ContainerFile:  The file which describes the pcd, used for error \r
+# @param ContainerFile:  The file which describes the pcd, used for error\r
 #                        report\r
 #\r
-def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo=-1):\r
+def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo= -1):\r
     TokenGuid, TokenName, List1, List2 = '', '', '', ''\r
     List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT)\r
     if len(List) < 3 or len(List) > 4:\r
@@ -272,7 +274,7 @@ def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo=-1):
 ## GetComponent\r
 #\r
 # Parse block of the components defined in dsc file\r
-# Set KeyValues as [ ['component name', [lib1, lib2, lib3], \r
+# Set KeyValues as [ ['component name', [lib1, lib2, lib3],\r
 # [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]\r
 #\r
 # @param Lines:             The content to be parsed\r
@@ -407,7 +409,7 @@ def GetExec(String):
 ## GetComponents\r
 #\r
 # Parse block of the components defined in dsc file\r
-# Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], \r
+# Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3],\r
 # [pcd1, pcd2, pcd3]], ...]\r
 #\r
 # @param Lines:             The content to be parsed\r
@@ -432,7 +434,7 @@ def GetComponents(Lines, KeyValues, CommentCharacter):
     LineList = Lines.split('\n')\r
     for Line in LineList:\r
         Line = CleanString(Line, CommentCharacter)\r
-        if Line == None or Line == '':\r
+        if Line is None or Line == '':\r
             continue\r
 \r
         if FindBlock == False:\r
@@ -530,10 +532,10 @@ def GetComponents(Lines, KeyValues, CommentCharacter):
 #\r
 # @param Item:           String as <Filename>[|<Family>[|<TagName>[|<ToolCode>\r
 #                        [|<PcdFeatureFlag>]]]]\r
-# @param ContainerFile:  The file which describes the library class, used \r
+# @param ContainerFile:  The file which describes the library class, used\r
 #                        for error report\r
 #\r
-def GetSource(Item, ContainerFile, FileRelativePath, LineNo=-1):\r
+def GetSource(Item, ContainerFile, FileRelativePath, LineNo= -1):\r
     ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4\r
     List = GetSplitValueList(ItemNew)\r
     if len(List) < 5 or len(List) > 9:\r
@@ -555,10 +557,10 @@ def GetSource(Item, ContainerFile, FileRelativePath, LineNo=-1):
 #\r
 # @param Item:           String as <Filename>[|<Family>[|<TagName>\r
 #                        [|<ToolCode>[|<PcdFeatureFlag>]]]]\r
-# @param ContainerFile:  The file which describes the library class, \r
+# @param ContainerFile:  The file which describes the library class,\r
 #                        used for error report\r
 #\r
-def GetBinary(Item, ContainerFile, LineNo=-1):\r
+def GetBinary(Item, ContainerFile, LineNo= -1):\r
     ItemNew = Item + DataType.TAB_VALUE_SPLIT\r
     List = GetSplitValueList(ItemNew)\r
     if len(List) < 3 or len(List) > 5:\r
@@ -579,7 +581,7 @@ def GetBinary(Item, ContainerFile, LineNo=-1):
 #\r
 # @param Item:           String as <GuidCName>[|<PcdFeatureFlag>]\r
 # @param Type:           Type of parsing string\r
-# @param ContainerFile:  The file which describes the library class, \r
+# @param ContainerFile:  The file which describes the library class,\r
 #                        used for error report\r
 #\r
 def GetGuidsProtocolsPpisOfInf(Item):\r
@@ -593,10 +595,10 @@ def GetGuidsProtocolsPpisOfInf(Item):
 #\r
 # @param Item:           String as <GuidCName>=<GuidValue>\r
 # @param Type:           Type of parsing string\r
-# @param ContainerFile:  The file which describes the library class, \r
+# @param ContainerFile:  The file which describes the library class,\r
 # used for error report\r
 #\r
-def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo=-1):\r
+def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo= -1):\r
     List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)\r
     if len(List) != 2:\r
         RaiseParserError(Item, Type, ContainerFile, '<CName>=<GuidValue>', \\r
@@ -614,7 +616,7 @@ def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo=-1):
             RegisterFormatGuid = List[1]\r
         else:\r
             RaiseParserError(Item, Type, ContainerFile, \\r
-                             'CFormat or RegisterFormat', LineNo) \r
+                             'CFormat or RegisterFormat', LineNo)\r
 \r
     return (List[0], RegisterFormatGuid)\r
 \r
@@ -624,10 +626,10 @@ def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo=-1):
 #\r
 # @param Item:           String as <PackagePath>[|<PcdFeatureFlag>]\r
 # @param Type:           Type of parsing string\r
-# @param ContainerFile:  The file which describes the library class, \r
+# @param ContainerFile:  The file which describes the library class,\r
 #                        used for error report\r
 #\r
-def GetPackage(Item, ContainerFile, FileRelativePath, LineNo=-1):\r
+def GetPackage(Item, ContainerFile, FileRelativePath, LineNo= -1):\r
     ItemNew = Item + DataType.TAB_VALUE_SPLIT\r
     List = GetSplitValueList(ItemNew)\r
     CheckFileType(List[0], '.Dec', ContainerFile, 'package', List[0], LineNo)\r
@@ -683,7 +685,7 @@ def GetPcdOfInf(Item, Type, File, LineNo):
 # @param File:  Dec file\r
 # @param LineNo:  Line number\r
 #\r
-def GetPcdOfDec(Item, Type, File, LineNo=-1):\r
+def GetPcdOfDec(Item, Type, File, LineNo= -1):\r
     Format = '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'\r
     TokenGuid, TokenName, Value, DatumType, Token = '', '', '', '', ''\r
     List = GetSplitValueList(Item)\r
@@ -756,7 +758,7 @@ def InsertSectionItems(Model, SectionItemList, ArchList, \
             LineValue, StartLine, Comment = SectionItem[0], \\r
             SectionItem[1], SectionItem[2]\r
 \r
-            Logger.Debug(4, ST.MSG_PARSING %LineValue)\r
+            Logger.Debug(4, ST.MSG_PARSING % LineValue)\r
             #\r
             # And then parse DEFINE statement\r
             #\r
@@ -782,7 +784,7 @@ def GenMetaDatSectionItem(Key, Value, List):
         List[Key] = [Value]\r
     else:\r
         List[Key].append(Value)\r
-        \r
+\r
 ## GetPkgInfoFromDec\r
 #\r
 # get package name, guid, version info from dec files\r
@@ -793,17 +795,23 @@ def GetPkgInfoFromDec(Path):
     PkgName = None\r
     PkgGuid = None\r
     PkgVersion = None\r
-    \r
+\r
     Path = Path.replace('\\', '/')\r
-    \r
+\r
     if not os.path.exists(Path):\r
-        Logger.Error("\nUPT", FILE_NOT_FOUND, File = Path)  \r
+        Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path)\r
 \r
     if Path in gPKG_INFO_DICT:\r
         return gPKG_INFO_DICT[Path]\r
 \r
     try:\r
-        DecParser = Dec(Path)\r
+        DecParser = None\r
+        if Path not in GlobalData.gPackageDict:\r
+            DecParser = Dec(Path)\r
+            GlobalData.gPackageDict[Path] = DecParser\r
+        else:\r
+            DecParser = GlobalData.gPackageDict[Path]\r
+\r
         PkgName = DecParser.GetPackageName()\r
         PkgGuid = DecParser.GetPackageGuid()\r
         PkgVersion = DecParser.GetPackageVersion()\r
@@ -819,22 +827,24 @@ def GetPkgInfoFromDec(Path):
 #\r
 def GetWorkspacePackage():\r
     DecFileList = []\r
-    WorkspaceDir = os.environ["WORKSPACE"]\r
-    for Root, Dirs, Files in os.walk(WorkspaceDir):\r
-        if 'CVS' in Dirs:\r
-            Dirs.remove('CVS')\r
-        if '.svn' in Dirs:\r
-            Dirs.remove('.svn')\r
-        for Dir in Dirs:\r
-            if Dir.startswith('.'):\r
-                Dirs.remove(Dir)\r
-        for FileSp in Files:\r
-            if FileSp.startswith('.'):\r
-                continue\r
-            Ext = os.path.splitext(FileSp)[1]\r
-            if Ext.lower() in ['.dec']:\r
-                DecFileList.append\\r
-                (os.path.normpath(os.path.join(Root, FileSp)))\r
+    WorkspaceDir = GlobalData.gWORKSPACE\r
+    PackageDir = GlobalData.gPACKAGE_PATH\r
+    for PkgRoot in [WorkspaceDir] + PackageDir:\r
+        for Root, Dirs, Files in os.walk(PkgRoot):\r
+            if 'CVS' in Dirs:\r
+                Dirs.remove('CVS')\r
+            if '.svn' in Dirs:\r
+                Dirs.remove('.svn')\r
+            for Dir in Dirs:\r
+                if Dir.startswith('.'):\r
+                    Dirs.remove(Dir)\r
+            for FileSp in Files:\r
+                if FileSp.startswith('.'):\r
+                    continue\r
+                Ext = os.path.splitext(FileSp)[1]\r
+                if Ext.lower() in ['.dec']:\r
+                    DecFileList.append\\r
+                    (os.path.normpath(os.path.join(Root, FileSp)))\r
     #\r
     # abstract package guid, version info from DecFile List\r
     #\r
@@ -843,7 +853,7 @@ def GetWorkspacePackage():
         (PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile)\r
         if PkgName and PkgGuid and PkgVersion:\r
             PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile))\r
-    \r
+\r
     return PkgList\r
 \r
 ## GetWorkspaceModule\r
@@ -852,7 +862,7 @@ def GetWorkspacePackage():
 #\r
 def GetWorkspaceModule():\r
     InfFileList = []\r
-    WorkspaceDir = os.environ["WORKSPACE"]\r
+    WorkspaceDir = GlobalData.gWORKSPACE\r
     for Root, Dirs, Files in os.walk(WorkspaceDir):\r
         if 'CVS' in Dirs:\r
             Dirs.remove('CVS')\r
@@ -870,7 +880,7 @@ def GetWorkspaceModule():
             if Ext.lower() in ['.inf']:\r
                 InfFileList.append\\r
                 (os.path.normpath(os.path.join(Root, FileSp)))\r
-    \r
+\r
     return InfFileList\r
 \r
 ## MacroParser used to parse macro definition\r
@@ -890,7 +900,7 @@ def MacroParser(Line, FileName, SectionType, FileLocalMacros):
         # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method\r
         #\r
         return None, None\r
-    \r
+\r
     TokenList = GetSplitValueList(LineContent[Match.end(1):], \\r
                                   DataType.TAB_EQUAL_SPLIT, 1)\r
     #\r
@@ -910,16 +920,16 @@ def MacroParser(Line, FileName, SectionType, FileLocalMacros):
     #\r
     if SectionType == DataType.MODEL_META_DATA_HEADER:\r
         FileLocalMacros[Name] = Value\r
-    \r
+\r
     ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL)\r
-    if ReIsValidMacroName.match(Name) == None:\r
-        Logger.Error('Parser', \r
-                     FORMAT_INVALID, \r
-                     ST.ERR_MACRONAME_INVALID%(Name),\r
-                     ExtraData=LineContent, \r
-                     File=FileName, \r
+    if ReIsValidMacroName.match(Name) is None:\r
+        Logger.Error('Parser',\r
+                     FORMAT_INVALID,\r
+                     ST.ERR_MACRONAME_INVALID % (Name),\r
+                     ExtraData=LineContent,\r
+                     File=FileName,\r
                      Line=LineNo)\r
-        \r
+\r
     # Validate MACRO Value\r
     #\r
     # <MacroDefinition> ::=  [<Comments>]{0,}\r
@@ -927,32 +937,32 @@ def MacroParser(Line, FileName, SectionType, FileLocalMacros):
     # <Value>           ::=  {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}\r
     #                        {<CString>} {<UnicodeString>} {<CArray>}\r
     #\r
-    # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>, \r
+    # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>,\r
     # <UnicodeString>, <CArray> are subset of <AsciiString>.\r
     #\r
     ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL)\r
-    if ReIsValidMacroValue.match(Value) == None:\r
-        Logger.Error('Parser', \r
-                     FORMAT_INVALID, \r
-                     ST.ERR_MACROVALUE_INVALID%(Value),\r
-                     ExtraData=LineContent, \r
-                     File=FileName, \r
+    if ReIsValidMacroValue.match(Value) is None:\r
+        Logger.Error('Parser',\r
+                     FORMAT_INVALID,\r
+                     ST.ERR_MACROVALUE_INVALID % (Value),\r
+                     ExtraData=LineContent,\r
+                     File=FileName,\r
                      Line=LineNo)\r
-        \r
+\r
     return Name, Value\r
 \r
-## GenSection \r
+## GenSection\r
 #\r
 # generate section contents\r
 #\r
-# @param  SectionName:  indicate the name of the section, details refer to \r
+# @param  SectionName:  indicate the name of the section, details refer to\r
 #                       INF, DEC specs\r
-# @param  SectionDict:  section statement dict, key is SectionAttrs(arch, \r
-#                       moduletype or platform may exist as needed) list \r
-#                       seperated by space, \r
+# @param  SectionDict:  section statement dict, key is SectionAttrs(arch,\r
+#                       moduletype or platform may exist as needed) list\r
+#                       seperated by space,\r
 #                       value is statement\r
 #\r
-def GenSection(SectionName, SectionDict, SplitArch=True):\r
+def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False):\r
     Content = ''\r
     for SectionAttrs in SectionDict:\r
         StatementList = SectionDict[SectionAttrs]\r
@@ -969,25 +979,43 @@ def GenSection(SectionName, SectionDict, SplitArch=True):
             Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']'\r
         else:\r
             Section = '[' + SectionName + ']'\r
-        Content += '\n\n' + Section + '\n'\r
-        if StatementList != None:\r
+        Content += '\n' + Section + '\n'\r
+        if StatementList is not None:\r
             for Statement in StatementList:\r
-                Content += Statement + '\n'\r
+                LineList = Statement.split('\n')\r
+                NewStatement = ""\r
+                for Line in LineList:\r
+                    # ignore blank comment\r
+                    if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'):\r
+                        continue\r
+                    # add two space before non-comments line except the comments in Defines section\r
+                    if Line.strip().startswith('#') and SectionName == 'Defines':\r
+                        NewStatement += "%s\n" % Line\r
+                        continue\r
+                    NewStatement += "  %s\n" % Line\r
+                if NeedBlankLine:\r
+                    Content += NewStatement + '\n'\r
+                else:\r
+                    Content += NewStatement\r
 \r
+        if NeedBlankLine:\r
+            Content = Content[:-1]\r
+    if not Content.replace('\\n', '').strip():\r
+        return ''\r
     return Content\r
 \r
 ## ConvertArchForInstall\r
-# if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case.  "common" must be lower case.  \r
+# if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case.  "common" must be lower case.\r
 # Anything else, the case must be preserved\r
 #\r
-# @param Arch: the arch string that need to be converted, it should be stripped before pass in \r
+# @param Arch: the arch string that need to be converted, it should be stripped before pass in\r
 # @return: the arch string that get converted\r
 #\r
 def ConvertArchForInstall(Arch):\r
-    if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64, \r
+    if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64,\r
                                    DataType.TAB_ARCH_IPF, DataType.TAB_ARCH_EBC]:\r
         Arch = Arch.upper()\r
     elif Arch.upper() == DataType.TAB_ARCH_COMMON:\r
         Arch = Arch.lower()\r
-    \r
+\r
     return Arch\r