]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/UPT/Library/Parsing.py
Sync BaseTools Branch (version r2271) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Library / Parsing.py
diff --git a/BaseTools/Source/Python/UPT/Library/Parsing.py b/BaseTools/Source/Python/UPT/Library/Parsing.py
new file mode 100644 (file)
index 0000000..95c5140
--- /dev/null
@@ -0,0 +1,993 @@
+## @file\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
+#\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
+\r
+'''\r
+Parsing\r
+'''\r
+\r
+##\r
+# Import Modules\r
+#\r
+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
+\r
+from Logger.ToolError import FILE_NOT_FOUND\r
+from Logger.ToolError import FatalError\r
+from Logger.ToolError import FORMAT_INVALID\r
+\r
+from Library import DataType\r
+\r
+from Library.Misc import GuidStructureStringToGuidString\r
+from Library.Misc import CheckGuidRegFormat\r
+from Logger import StringTable as ST\r
+import Logger.Log as Logger\r
+\r
+from Parser.DecParser import Dec\r
+\r
+gPKG_INFO_DICT = {}\r
+\r
+## GetBuildOption\r
+#\r
+# Parse a string with format "[<Family>:]<ToolFlag>=Flag"\r
+# Return (Family, ToolFlag, Flag)\r
+#\r
+# @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
+    (Family, ToolChain, Flag) = ('', '', '')\r
+    if String.find(DataType.TAB_EQUAL_SPLIT) < 0:\r
+        RaiseParserError(String, 'BuildOptions', File, \\r
+                         '[<Family>:]<ToolFlag>=Flag', LineNo)\r
+    else:\r
+        List = GetSplitValueList(String, DataType.TAB_EQUAL_SPLIT, MaxSplit=1)\r
+        if List[0].find(':') > -1:\r
+            Family = List[0][ : List[0].find(':')].strip()\r
+            ToolChain = List[0][List[0].find(':') + 1 : ].strip()\r
+        else:\r
+            ToolChain = List[0].strip()\r
+        Flag = List[1].strip()\r
+    return (Family, ToolChain, Flag)\r
+\r
+## Get Library Class\r
+#\r
+# 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
+#                        error report\r
+#\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
+        RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, \\r
+                         '<LibraryClassKeyWord>|<LibraryInstance>')\r
+    else:\r
+        CheckFileType(List[1], '.Inf', ContainerFile, \\r
+                      'library class instance', Item[0], LineNo)\r
+        CheckFileExist(WorkspaceDir, List[1], ContainerFile, \\r
+                       'LibraryClasses', Item[0], LineNo)\r
+        if Item[1] != '':\r
+            SupMod = Item[1]\r
+\r
+    return (List[0], List[1], SupMod)\r
+\r
+## Get Library Class\r
+#\r
+# Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>]\r
+# [|<TokenSpaceGuidCName>.<PcdCName>]\r
+#\r
+# @param Item:           String as <LibraryClassKeyWord>|<LibraryInstance>\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
+    ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2))\r
+    SupMod = DataType.SUP_MODULE_LIST_STRING\r
+\r
+    if len(ItemList) > 5:\r
+        RaiseParserError\\r
+        (Item[0], 'LibraryClasses', ContainerFile, \\r
+         '<LibraryClassKeyWord>[|<LibraryInstance>]\\r
+         [|<TokenSpaceGuidCName>.<PcdCName>]')\r
+    else:\r
+        CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', \\r
+                      Item[0], LineNo)\r
+        CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, \\r
+                       'LibraryClasses', Item[0], LineNo)\r
+        if ItemList[2] != '':\r
+            CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', \\r
+                              ContainerFile, LineNo)\r
+        if Item[1] != '':\r
+            SupMod = Item[1]\r
+\r
+    return (ItemList[0], ItemList[1], ItemList[2], SupMod)\r
+\r
+## CheckPcdTokenInfo\r
+#\r
+# Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>\r
+#\r
+# @param TokenInfoString:  String to be checked\r
+# @param Section:          Used for error report\r
+# @param File:             Used for error report\r
+#\r
+def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo=-1):\r
+    Format = '<TokenSpaceGuidCName>.<PcdCName>'\r
+    if TokenInfoString != '' and TokenInfoString != None:\r
+        TokenInfoList = GetSplitValueList(TokenInfoString, DataType.TAB_SPLIT)\r
+        if len(TokenInfoList) == 2:\r
+            return True\r
+\r
+    RaiseParserError(TokenInfoString, Section, File, Format, LineNo)\r
+\r
+## Get Pcd\r
+#\r
+# Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\r
+# [|<Type>|<MaximumDatumSize>]\r
+#\r
+# @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|\r
+#                        <Value>[|<Type>|<MaximumDatumSize>]\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
+    TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', ''\r
+    List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)\r
+\r
+    if len(List) < 4 or len(List) > 6:\r
+        RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \\r
+                         '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\\r
+                         [|<Type>|<MaximumDatumSize>]', LineNo)\r
+    else:\r
+        Value = List[1]\r
+        MaximumDatumSize = List[2]\r
+        Token = List[3]\r
+\r
+    if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):\r
+        (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
+\r
+    return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type)\r
+\r
+## Get FeatureFlagPcd\r
+#\r
+# Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE\r
+#\r
+# @param Item:           String as <PcdTokenSpaceGuidCName>\r
+#                        .<TokenCName>|TRUE/FALSE\r
+# @param ContainerFile:  The file which describes the pcd, used for error \r
+#                        report\r
+#\r
+def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo=-1):\r
+    TokenGuid, TokenName, Value = '', '', ''\r
+    List = GetSplitValueList(Item)\r
+    if len(List) != 2:\r
+        RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \\r
+                         '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \\r
+                         LineNo)\r
+    else:\r
+        Value = List[1]\r
+    if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):\r
+        (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
+\r
+    return (TokenName, TokenGuid, Value, Type)\r
+\r
+## Get DynamicDefaultPcd\r
+#\r
+# Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>\r
+# |<Value>[|<DatumTyp>[|<MaxDatumSize>]]\r
+#\r
+# @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|\r
+#                        TRUE/FALSE\r
+# @param ContainerFile:  The file which describes the pcd, used for error \r
+#                        report\r
+#\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
+        RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \\r
+                         '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\\r
+                         [|<DatumTyp>[|<MaxDatumSize>]]', LineNo)\r
+    else:\r
+        Value = List[1]\r
+        DatumTyp = List[2]\r
+        MaxDatumSize = List[3]\r
+    if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):\r
+        (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
+\r
+    return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type)\r
+\r
+## Get DynamicHiiPcd\r
+#\r
+# Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|\r
+# <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]\r
+#\r
+# @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|\r
+#                        TRUE/FALSE\r
+# @param ContainerFile:  The file which describes the pcd, used for error \r
+#                        report\r
+#\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
+    if len(List) < 6 or len(List) > 8:\r
+        RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \\r
+                         '<PcdTokenSpaceGuidCName>.<TokenCName>|<String>|\\r
+                         <VariableGuidCName>|<VariableOffset>[|<DefaultValue>\\r
+                         [|<MaximumDatumSize>]]', LineNo)\r
+    else:\r
+        List1, List2, List3, List4, List5 = \\r
+        List[1], List[2], List[3], List[4], List[5]\r
+    if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):\r
+        (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
+\r
+    return (TokenName, TokenGuid, List1, List2, List3, List4, List5, Type)\r
+\r
+## Get DynamicVpdPcd\r
+#\r
+# Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|\r
+# <VpdOffset>[|<MaximumDatumSize>]\r
+#\r
+# @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>\r
+#                        |TRUE/FALSE\r
+# @param ContainerFile:  The file which describes the pcd, used for error \r
+#                        report\r
+#\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
+        RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \\r
+                         '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>\\r
+                         [|<MaximumDatumSize>]', LineNo)\r
+    else:\r
+        List1, List2 = List[1], List[2]\r
+    if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):\r
+        (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
+\r
+    return (TokenName, TokenGuid, List1, List2, Type)\r
+\r
+## GetComponent\r
+#\r
+# Parse block of the components defined in dsc file\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
+# @param KeyValues:         To store data after parsing\r
+#\r
+def GetComponent(Lines, KeyValues):\r
+    (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+     FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \\r
+     FindPcdsDynamicEx) = (False, False, False, False, False, False, False, \\r
+                           False)\r
+    ListItem = None\r
+    LibraryClassItem = []\r
+    BuildOption = []\r
+    Pcd = []\r
+\r
+    for Line in Lines:\r
+        Line = Line[0]\r
+        #\r
+        # Ignore !include statement\r
+        #\r
+        if Line.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1 or \\r
+        Line.upper().find(DataType.TAB_DEFINE + ' ') > -1:\r
+            continue\r
+\r
+        if FindBlock == False:\r
+            ListItem = Line\r
+            #\r
+            # find '{' at line tail\r
+            #\r
+            if Line.endswith('{'):\r
+                FindBlock = True\r
+                ListItem = CleanString(Line.rsplit('{', 1)[0], \\r
+                                       DataType.TAB_COMMENT_SPLIT)\r
+\r
+        #\r
+        # Parse a block content\r
+        #\r
+        if FindBlock:\r
+            if Line.find('<LibraryClasses>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (True, False, False, False, False, False, False)\r
+                continue\r
+            if Line.find('<BuildOptions>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, True, False, False, False, False, False)\r
+                continue\r
+            if Line.find('<PcdsFeatureFlag>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, True, False, False, False, False)\r
+                continue\r
+            if Line.find('<PcdsPatchableInModule>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, True, False, False, False)\r
+                continue\r
+            if Line.find('<PcdsFixedAtBuild>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, False, True, False, False)\r
+                continue\r
+            if Line.find('<PcdsDynamic>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, False, False, True, False)\r
+                continue\r
+            if Line.find('<PcdsDynamicEx>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, False, False, False, True)\r
+                continue\r
+            if Line.endswith('}'):\r
+                #\r
+                # find '}' at line tail\r
+                #\r
+                KeyValues.append([ListItem, LibraryClassItem, \\r
+                                  BuildOption, Pcd])\r
+                (FindBlock, FindLibraryClass, FindBuildOption, \\r
+                 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \\r
+                 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, False, False, False, False, False)\r
+                LibraryClassItem, BuildOption, Pcd = [], [], []\r
+                continue\r
+\r
+        if FindBlock:\r
+            if FindLibraryClass:\r
+                LibraryClassItem.append(Line)\r
+            elif FindBuildOption:\r
+                BuildOption.append(Line)\r
+            elif FindPcdsFeatureFlag:\r
+                Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG_NULL, Line))\r
+            elif FindPcdsPatchableInModule:\r
+                Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE_NULL, Line))\r
+            elif FindPcdsFixedAtBuild:\r
+                Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD_NULL, Line))\r
+            elif FindPcdsDynamic:\r
+                Pcd.append((DataType.TAB_PCDS_DYNAMIC_DEFAULT_NULL, Line))\r
+            elif FindPcdsDynamicEx:\r
+                Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, Line))\r
+        else:\r
+            KeyValues.append([ListItem, [], [], []])\r
+\r
+    return True\r
+\r
+## GetExec\r
+#\r
+# Parse a string with format "InfFilename [EXEC = ExecFilename]"\r
+# Return (InfFilename, ExecFilename)\r
+#\r
+# @param String:  String with EXEC statement\r
+#\r
+def GetExec(String):\r
+    InfFilename = ''\r
+    ExecFilename = ''\r
+    if String.find('EXEC') > -1:\r
+        InfFilename = String[ : String.find('EXEC')].strip()\r
+        ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip()\r
+    else:\r
+        InfFilename = String.strip()\r
+\r
+    return (InfFilename, ExecFilename)\r
+\r
+## 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
+# [pcd1, pcd2, pcd3]], ...]\r
+#\r
+# @param Lines:             The content to be parsed\r
+# @param Key:               Reserved\r
+# @param KeyValues:         To store data after parsing\r
+# @param CommentCharacter:  Comment char, used to ignore comment content\r
+#\r
+# @retval True Get component successfully\r
+#\r
+def GetComponents(Lines, KeyValues, CommentCharacter):\r
+    if Lines.find(DataType.TAB_SECTION_END) > -1:\r
+        Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
+    (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+     FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \\r
+     FindPcdsDynamicEx) = \\r
+     (False, False, False, False, False, False, False, False)\r
+    ListItem = None\r
+    LibraryClassItem = []\r
+    BuildOption = []\r
+    Pcd = []\r
+\r
+    LineList = Lines.split('\n')\r
+    for Line in LineList:\r
+        Line = CleanString(Line, CommentCharacter)\r
+        if Line == None or Line == '':\r
+            continue\r
+\r
+        if FindBlock == False:\r
+            ListItem = Line\r
+            #\r
+            # find '{' at line tail\r
+            #\r
+            if Line.endswith('{'):\r
+                FindBlock = True\r
+                ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter)\r
+\r
+        #\r
+        # Parse a block content\r
+        #\r
+        if FindBlock:\r
+            if Line.find('<LibraryClasses>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (True, False, False, False, False, False, False)\r
+                continue\r
+            if Line.find('<BuildOptions>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, True, False, False, False, False, False)\r
+                continue\r
+            if Line.find('<PcdsFeatureFlag>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, True, False, False, False, False)\r
+                continue\r
+            if Line.find('<PcdsPatchableInModule>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, True, False, False, False)\r
+                continue\r
+            if Line.find('<PcdsFixedAtBuild>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, False, True, False, False)\r
+                continue\r
+            if Line.find('<PcdsDynamic>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, False, False, True, False)\r
+                continue\r
+            if Line.find('<PcdsDynamicEx>') != -1:\r
+                (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \\r
+                 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \\r
+                 FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, False, False, False, True)\r
+                continue\r
+            if Line.endswith('}'):\r
+                #\r
+                # find '}' at line tail\r
+                #\r
+                KeyValues.append([ListItem, LibraryClassItem, BuildOption, \\r
+                                  Pcd])\r
+                (FindBlock, FindLibraryClass, FindBuildOption, \\r
+                 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \\r
+                 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \\r
+                 (False, False, False, False, False, False, False, False)\r
+                LibraryClassItem, BuildOption, Pcd = [], [], []\r
+                continue\r
+\r
+        if FindBlock:\r
+            if FindLibraryClass:\r
+                LibraryClassItem.append(Line)\r
+            elif FindBuildOption:\r
+                BuildOption.append(Line)\r
+            elif FindPcdsFeatureFlag:\r
+                Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG, Line))\r
+            elif FindPcdsPatchableInModule:\r
+                Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE, Line))\r
+            elif FindPcdsFixedAtBuild:\r
+                Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD, Line))\r
+            elif FindPcdsDynamic:\r
+                Pcd.append((DataType.TAB_PCDS_DYNAMIC, Line))\r
+            elif FindPcdsDynamicEx:\r
+                Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX, Line))\r
+        else:\r
+            KeyValues.append([ListItem, [], [], []])\r
+\r
+    return True\r
+\r
+## Get Source\r
+#\r
+# Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>\r
+# [|<PcdFeatureFlag>]]]]\r
+#\r
+# @param Item:           String as <Filename>[|<Family>[|<TagName>[|<ToolCode>\r
+#                        [|<PcdFeatureFlag>]]]]\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
+    ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4\r
+    List = GetSplitValueList(ItemNew)\r
+    if len(List) < 5 or len(List) > 9:\r
+        RaiseParserError(Item, 'Sources', ContainerFile, \\r
+                         '<Filename>[|<Family>[|<TagName>[|<ToolCode>\\r
+                         [|<PcdFeatureFlag>]]]]', LineNo)\r
+    List[0] = NormPath(List[0])\r
+    CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Sources', \\r
+                   Item, LineNo)\r
+    if List[4] != '':\r
+        CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo)\r
+\r
+    return (List[0], List[1], List[2], List[3], List[4])\r
+\r
+## Get Binary\r
+#\r
+# Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>\r
+# [|<PcdFeatureFlag>]]]]\r
+#\r
+# @param Item:           String as <Filename>[|<Family>[|<TagName>\r
+#                        [|<ToolCode>[|<PcdFeatureFlag>]]]]\r
+# @param ContainerFile:  The file which describes the library class, \r
+#                        used for error report\r
+#\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
+        RaiseParserError(Item, 'Binaries', ContainerFile, \\r
+                         "<FileType>|<Filename>[|<Target>\\r
+                         [|<TokenSpaceGuidCName>.<PcdCName>]]", LineNo)\r
+\r
+    if len(List) >= 4:\r
+        if List[3] != '':\r
+            CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo)\r
+        return (List[0], List[1], List[2], List[3])\r
+    elif len(List) == 3:\r
+        return (List[0], List[1], List[2], '')\r
+\r
+## Get Guids/Protocols/Ppis\r
+#\r
+# Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]\r
+#\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
+#                        used for error report\r
+#\r
+def GetGuidsProtocolsPpisOfInf(Item):\r
+    ItemNew = Item + DataType.TAB_VALUE_SPLIT\r
+    List = GetSplitValueList(ItemNew)\r
+    return (List[0], List[1])\r
+\r
+## Get Guids/Protocols/Ppis\r
+#\r
+# Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>\r
+#\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
+# used for error report\r
+#\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
+                         LineNo)\r
+    #\r
+    #convert C-Format Guid to Register Format\r
+    #\r
+    if List[1][0] == '{' and List[1][-1] == '}':\r
+        RegisterFormatGuid = GuidStructureStringToGuidString(List[1])\r
+        if RegisterFormatGuid == '':\r
+            RaiseParserError(Item, Type, ContainerFile, \\r
+                             'CFormat or RegisterFormat', LineNo)\r
+    else:\r
+        if CheckGuidRegFormat(List[1]):\r
+            RegisterFormatGuid = List[1]\r
+        else:\r
+            RaiseParserError(Item, Type, ContainerFile, \\r
+                             'CFormat or RegisterFormat', LineNo) \r
+\r
+    return (List[0], RegisterFormatGuid)\r
+\r
+## GetPackage\r
+#\r
+# Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]\r
+#\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
+#                        used for error report\r
+#\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
+    CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Packages', \\r
+                   List[0], LineNo)\r
+    if List[1] != '':\r
+        CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo)\r
+\r
+    return (List[0], List[1])\r
+\r
+## Get Pcd Values of Inf\r
+#\r
+# Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]\r
+#\r
+# @param Item:  The string describes pcd\r
+# @param Type:  The type of Pcd\r
+# @param File:  The file which describes the pcd, used for error report\r
+#\r
+def GetPcdOfInf(Item, Type, File, LineNo):\r
+    Format = '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'\r
+    TokenGuid, TokenName, Value, InfType = '', '', '', ''\r
+\r
+    if Type == DataType.TAB_PCDS_FIXED_AT_BUILD:\r
+        InfType = DataType.TAB_INF_FIXED_PCD\r
+    elif Type == DataType.TAB_PCDS_PATCHABLE_IN_MODULE:\r
+        InfType = DataType.TAB_INF_PATCH_PCD\r
+    elif Type == DataType.TAB_PCDS_FEATURE_FLAG:\r
+        InfType = DataType.TAB_INF_FEATURE_PCD\r
+    elif Type == DataType.TAB_PCDS_DYNAMIC_EX:\r
+        InfType = DataType.TAB_INF_PCD_EX\r
+    elif Type == DataType.TAB_PCDS_DYNAMIC:\r
+        InfType = DataType.TAB_INF_PCD\r
+    List = GetSplitValueList(Item, DataType.TAB_VALUE_SPLIT, 1)\r
+    TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
+    if len(TokenInfo) != 2:\r
+        RaiseParserError(Item, InfType, File, Format, LineNo)\r
+    else:\r
+        TokenGuid = TokenInfo[0]\r
+        TokenName = TokenInfo[1]\r
+\r
+    if len(List) > 1:\r
+        Value = List[1]\r
+    else:\r
+        Value = None\r
+    return (TokenGuid, TokenName, Value, InfType)\r
+\r
+\r
+## Get Pcd Values of Dec\r
+#\r
+# Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>\r
+# @param Item:  Pcd item\r
+# @param Type:  Pcd type\r
+# @param File:  Dec file\r
+# @param LineNo:  Line number\r
+#\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
+    if len(List) != 4:\r
+        RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)\r
+    else:\r
+        Value = List[1]\r
+        DatumType = List[2]\r
+        Token = List[3]\r
+    TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
+    if len(TokenInfo) != 2:\r
+        RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)\r
+    else:\r
+        TokenGuid = TokenInfo[0]\r
+        TokenName = TokenInfo[1]\r
+\r
+    return (TokenGuid, TokenName, Value, DatumType, Token, Type)\r
+\r
+## Parse DEFINE statement\r
+#\r
+# Get DEFINE macros\r
+#\r
+# @param LineValue:  A DEFINE line value\r
+# @param StartLine:  A DEFINE start line\r
+# @param Table:      A table\r
+# @param FileID:     File ID\r
+# @param Filename:   File name\r
+# @param SectionName:  DEFINE section name\r
+# @param SectionModel:  DEFINE section model\r
+# @param Arch:   DEFINE arch\r
+#\r
+def ParseDefine(LineValue, StartLine, Table, FileID, SectionName, \\r
+                SectionModel, Arch):\r
+    Logger.Debug(Logger.DEBUG_2, ST.MSG_DEFINE_STATEMENT_FOUND % (LineValue, \\r
+                                                                  SectionName))\r
+    Define = \\r
+    GetSplitValueList(CleanString\\r
+                      (LineValue[LineValue.upper().\\r
+                                 find(DataType.TAB_DEFINE.upper() + ' ') + \\r
+                                 len(DataType.TAB_DEFINE + ' ') : ]), \\r
+                                 DataType.TAB_EQUAL_SPLIT, 1)\r
+    Table.Insert(DataType.MODEL_META_DATA_DEFINE, Define[0], Define[1], '', \\r
+                 '', '', Arch, SectionModel, FileID, StartLine, -1, \\r
+                 StartLine, -1, 0)\r
+\r
+## InsertSectionItems\r
+#\r
+# Insert item data of a section to a dict\r
+#\r
+# @param Model:   A model\r
+# @param CurrentSection:   Current section\r
+# @param SectionItemList:   Section item list\r
+# @param ArchList:   Arch list\r
+# @param ThirdList:   Third list\r
+# @param RecordSet:   Record set\r
+#\r
+def InsertSectionItems(Model, SectionItemList, ArchList, \\r
+                       ThirdList, RecordSet):\r
+    #\r
+    # Insert each item data of a section\r
+    #\r
+    for Index in range(0, len(ArchList)):\r
+        Arch = ArchList[Index]\r
+        Third = ThirdList[Index]\r
+        if Arch == '':\r
+            Arch = DataType.TAB_ARCH_COMMON\r
+\r
+        Records = RecordSet[Model]\r
+        for SectionItem in SectionItemList:\r
+            LineValue, StartLine, Comment = SectionItem[0], \\r
+            SectionItem[1], SectionItem[2]\r
+\r
+            Logger.Debug(4, ST.MSG_PARSING %LineValue)\r
+            #\r
+            # And then parse DEFINE statement\r
+            #\r
+            if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1:\r
+                continue\r
+            #\r
+            # At last parse other sections\r
+            #\r
+            IdNum = -1\r
+            Records.append([LineValue, Arch, StartLine, IdNum, Third, Comment])\r
+\r
+        if RecordSet != {}:\r
+            RecordSet[Model] = Records\r
+\r
+## GenMetaDatSectionItem\r
+#\r
+# @param Key:    A key\r
+# @param Value:  A value\r
+# @param List:   A list\r
+#\r
+def GenMetaDatSectionItem(Key, Value, List):\r
+    if Key not in List:\r
+        List[Key] = [Value]\r
+    else:\r
+        List[Key].append(Value)\r
+        \r
+## GetPkgInfoFromDec\r
+#\r
+# get package name, guid, version info from dec files\r
+#\r
+# @param Path:   File path\r
+#\r
+def GetPkgInfoFromDec(Path):\r
+    PkgName = None\r
+    PkgGuid = None\r
+    PkgVersion = None\r
+    \r
+    Path = Path.replace('\\', '/')\r
+    \r
+    if not os.path.exists(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
+        PkgName = DecParser.GetPackageName()\r
+        PkgGuid = DecParser.GetPackageGuid()\r
+        PkgVersion = DecParser.GetPackageVersion()\r
+        gPKG_INFO_DICT[Path] = (PkgName, PkgGuid, PkgVersion)\r
+        return PkgName, PkgGuid, PkgVersion\r
+    except FatalError:\r
+        return None, None, None\r
+\r
+\r
+## GetWorkspacePackage\r
+#\r
+# Get a list of workspace package information.\r
+#\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
+    #\r
+    # abstract package guid, version info from DecFile List\r
+    #\r
+    PkgList = []\r
+    for DecFile in DecFileList:\r
+        (PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile)\r
+        if PkgName and PkgGuid and PkgVersion:\r
+            PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile))\r
+    \r
+    return PkgList\r
+\r
+## GetWorkspaceModule\r
+#\r
+# Get a list of workspace modules.\r
+#\r
+def GetWorkspaceModule():\r
+    InfFileList = []\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
+        if 'Build' in Dirs:\r
+            Dirs.remove('Build')\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 ['.inf']:\r
+                InfFileList.append\\r
+                (os.path.normpath(os.path.join(Root, FileSp)))\r
+    \r
+    return InfFileList\r
+\r
+## MacroParser used to parse macro definition\r
+#\r
+# @param Line:            The content contain linestring and line number\r
+# @param FileName:        The meta-file file name\r
+# @param SectionType:     Section for the Line belong to\r
+# @param FileLocalMacros: A list contain Macro defined in [Defines] section.\r
+#\r
+def MacroParser(Line, FileName, SectionType, FileLocalMacros):\r
+    MacroDefPattern = re.compile("^(DEFINE)[ \t]+")\r
+    LineContent = Line[0]\r
+    LineNo = Line[1]\r
+    Match = MacroDefPattern.match(LineContent)\r
+    if not Match:\r
+        #\r
+        # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method\r
+        #\r
+        return None, None\r
+    \r
+    TokenList = GetSplitValueList(LineContent[Match.end(1):], \\r
+                                  DataType.TAB_EQUAL_SPLIT, 1)\r
+    #\r
+    # Syntax check\r
+    #\r
+    if not TokenList[0]:\r
+        Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACRONAME_NOGIVEN,\r
+                        ExtraData=LineContent, File=FileName, Line=LineNo)\r
+    if len(TokenList) < 2:\r
+        Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACROVALUE_NOGIVEN,\r
+                        ExtraData=LineContent, File=FileName, Line=LineNo)\r
+\r
+    Name, Value = TokenList\r
+\r
+    #\r
+    # DEFINE defined macros\r
+    #\r
+    if SectionType == DataType.MODEL_META_DATA_HEADER:\r
+        FileLocalMacros[Name] = Value\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
+                     Line=LineNo)\r
+        \r
+    # Validate MACRO Value\r
+    #\r
+    # <MacroDefinition> ::=  [<Comments>]{0,}\r
+    #                       "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>\r
+    # <Value>           ::=  {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}\r
+    #                        {<CString>} {<UnicodeString>} {<CArray>}\r
+    #\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
+                     Line=LineNo)\r
+        \r
+    return Name, Value\r
+\r
+## GenSection \r
+#\r
+# generate section contents\r
+#\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
+#                       value is statement\r
+#\r
+def GenSection(SectionName, SectionDict, SplitArch=True):\r
+    Content = ''\r
+    for SectionAttrs in SectionDict:\r
+        StatementList = SectionDict[SectionAttrs]\r
+        if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON:\r
+            if SplitArch:\r
+                ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT)\r
+            else:\r
+                if SectionName != 'UserExtensions':\r
+                    ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT)\r
+                else:\r
+                    ArchList = [SectionAttrs]\r
+            for Index in xrange(0, len(ArchList)):\r
+                ArchList[Index] = ConvertArchForInstall(ArchList[Index])\r
+            Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']'\r
+        else:\r
+            Section = '[' + SectionName + ']'\r
+        Content += '\n\n' + Section + '\n'\r
+        if StatementList != None:\r
+            for Statement in StatementList:\r
+                Content += Statement + '\n'\r
+\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
+# 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
+# @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
+                                   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
+    return Arch\r