]> git.proxmox.com Git - mirror_edk2.git/commitdiff
BaseTools: Rename String to StringUtils.
authorMarvin.Haeuser@outlook.com <Marvin.Haeuser@outlook.com>
Sat, 19 May 2018 10:50:25 +0000 (18:50 +0800)
committerLiming Gao <liming.gao@intel.com>
Mon, 28 May 2018 05:05:00 +0000 (13:05 +0800)
For case-insensitive file systems, edk2 String.py collides with the
Python string.py, which results in build errors. This,for example,
applies to building via the Windows Subsystem for Linux from a
DriveFS file system. This patch renames String to StringUtils to
prevent conflicts for case-insensitive file systems.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marvin Haeuser <Marvin.Haeuser@outlook.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
44 files changed:
BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools/Source/Python/AutoGen/BuildEngine.py
BaseTools/Source/Python/AutoGen/GenC.py
BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools/Source/Python/AutoGen/GenPcdDb.py
BaseTools/Source/Python/AutoGen/IdfClassObject.py
BaseTools/Source/Python/AutoGen/UniClassObject.py
BaseTools/Source/Python/Common/Database.py
BaseTools/Source/Python/Common/Parsing.py
BaseTools/Source/Python/Common/String.py [deleted file]
BaseTools/Source/Python/Common/StringUtils.py [new file with mode: 0644]
BaseTools/Source/Python/Common/ToolDefClassObject.py
BaseTools/Source/Python/Ecc/Configuration.py
BaseTools/Source/Python/Ecc/Ecc.py
BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py
BaseTools/Source/Python/Eot/Eot.py
BaseTools/Source/Python/Eot/InfParserLite.py
BaseTools/Source/Python/Eot/Parser.py
BaseTools/Source/Python/GenFds/AprioriSection.py
BaseTools/Source/Python/GenFds/FdfParser.py
BaseTools/Source/Python/GenFds/FfsInfStatement.py
BaseTools/Source/Python/GenFds/GenFds.py
BaseTools/Source/Python/GenFds/OptRomInfStatement.py
BaseTools/Source/Python/Makefile
BaseTools/Source/Python/Table/TableDataModel.py
BaseTools/Source/Python/Table/TableDec.py
BaseTools/Source/Python/Table/TableDsc.py
BaseTools/Source/Python/Table/TableEotReport.py
BaseTools/Source/Python/Table/TableFdf.py
BaseTools/Source/Python/Table/TableFile.py
BaseTools/Source/Python/Table/TableFunction.py
BaseTools/Source/Python/Table/TableIdentifier.py
BaseTools/Source/Python/Table/TableInf.py
BaseTools/Source/Python/Table/TablePcd.py
BaseTools/Source/Python/Table/TableQuery.py
BaseTools/Source/Python/Table/TableReport.py
BaseTools/Source/Python/UPT/Library/String.py [deleted file]
BaseTools/Source/Python/UPT/Library/StringUtils.py [new file with mode: 0644]
BaseTools/Source/Python/Workspace/DecBuildData.py
BaseTools/Source/Python/Workspace/DscBuildData.py
BaseTools/Source/Python/Workspace/InfBuildData.py
BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
BaseTools/Source/Python/build/BuildReport.py

index cf58abf25184bd917ea144aa15861edae079532a..9a57b9abd99242598db285620a3ac37eb70973ba 100644 (file)
@@ -33,7 +33,7 @@ from Common.LongFilePathSupport import CopyLongFilePath
 from Common.BuildToolError import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from Common.BuildToolError import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 import Common.GlobalData as GlobalData\r
 from GenFds.FdfParser import *\r
 from CommonDataClass.CommonClass import SkuInfoClass\r
 import Common.GlobalData as GlobalData\r
 from GenFds.FdfParser import *\r
 from CommonDataClass.CommonClass import SkuInfoClass\r
index dd6301b01fce4dc3499b7847ae2b0a43631ae8c5..ad1919442e6e8db05d72a11042661bfb89e52fef 100644 (file)
@@ -23,7 +23,7 @@ from Common.LongFilePathSupport import OpenLongFilePath as open
 from Common.GlobalData import *\r
 from Common.BuildToolError import *\r
 from Common.Misc import tdict, PathClass\r
 from Common.GlobalData import *\r
 from Common.BuildToolError import *\r
 from Common.Misc import tdict, PathClass\r
-from Common.String import NormPath\r
+from Common.StringUtils import NormPath\r
 from Common.DataType import *\r
 \r
 import Common.EdkLogger as EdkLogger\r
 from Common.DataType import *\r
 \r
 import Common.EdkLogger as EdkLogger\r
index 40a343ca1057eb5e7b037505e628bd147ed36103..1be27d2b89e0f1b75cade3d7c2626eeb6b5ffa94 100644 (file)
@@ -21,7 +21,7 @@ from Common import EdkLogger
 from Common.BuildToolError import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from Common.BuildToolError import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
-from Common.String import StringToArray\r
+from Common.StringUtils import StringToArray\r
 from StrGather import *\r
 from GenPcdDb import CreatePcdDatabaseCode\r
 from IdfClassObject import *\r
 from StrGather import *\r
 from GenPcdDb import CreatePcdDatabaseCode\r
 from IdfClassObject import *\r
index a373507422403e6b40ba882ecab90364ae39b9c6..6e83b3d73e61ce7a71c4ef619831cb411181794a 100644 (file)
@@ -22,7 +22,7 @@ from Common.LongFilePathSupport import OpenLongFilePath as open
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 from Common.BuildToolError import *\r
 from Common.Misc import *\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 from Common.BuildToolError import *\r
 from Common.Misc import *\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from BuildEngine import *\r
 import Common.GlobalData as GlobalData\r
 from collections import OrderedDict\r
 from BuildEngine import *\r
 import Common.GlobalData as GlobalData\r
 from collections import OrderedDict\r
index d2d42fe9d08eb5bd0d55423186c2da2701aa89db..2e05b77e14c2aa60a3d3fa3cb5b3d80768f3ba17 100644 (file)
@@ -12,7 +12,7 @@
 #\r
 from StringIO import StringIO\r
 from Common.Misc import *\r
 #\r
 from StringIO import StringIO\r
 from Common.Misc import *\r
-from Common.String import StringToArray\r
+from Common.StringUtils import StringToArray\r
 from struct import pack\r
 from ValidCheckingInfoObject import VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER\r
 from ValidCheckingInfoObject import VAR_CHECK_PCD_VARIABLE_TAB\r
 from struct import pack\r
 from ValidCheckingInfoObject import VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER\r
 from ValidCheckingInfoObject import VAR_CHECK_PCD_VARIABLE_TAB\r
index 769790d965b5c5c6857113ce05c388768770ae15..e5b933c2036fc07fd9e4e6f3687b63095ca7ecb2 100644 (file)
@@ -16,7 +16,7 @@
 import Common.EdkLogger as EdkLogger\r
 import StringIO\r
 from Common.BuildToolError import *\r
 import Common.EdkLogger as EdkLogger\r
 import StringIO\r
 from Common.BuildToolError import *\r
-from Common.String import GetLineNo\r
+from Common.StringUtils import GetLineNo\r
 from Common.Misc import PathClass\r
 from Common.LongFilePathSupport import LongFilePath\r
 import re\r
 from Common.Misc import PathClass\r
 from Common.LongFilePathSupport import LongFilePath\r
 import re\r
index 54b6fb22a08ad6881b78f9d5ec7fb8250e430176..5a3c2547783b3ff38b4bb41c8536672ae93beb3c 100644 (file)
@@ -21,7 +21,7 @@ import distutils.util
 import Common.EdkLogger as EdkLogger\r
 import StringIO\r
 from Common.BuildToolError import *\r
 import Common.EdkLogger as EdkLogger\r
 import StringIO\r
 from Common.BuildToolError import *\r
-from Common.String import GetLineNo\r
+from Common.StringUtils import GetLineNo\r
 from Common.Misc import PathClass\r
 from Common.LongFilePathSupport import LongFilePath\r
 from Common.GlobalData import *\r
 from Common.Misc import PathClass\r
 from Common.LongFilePathSupport import LongFilePath\r
 from Common.GlobalData import *\r
index a81a44731f03539e4e6dccd544650ff3a7c1ecb4..d3340f5a90369058dfe7356e72c1ab848ec9a622 100644 (file)
@@ -19,7 +19,7 @@ import Common.LongFilePathOs as os
 \r
 import EdkLogger as EdkLogger\r
 from CommonDataClass.DataClass import *\r
 \r
 import EdkLogger as EdkLogger\r
 from CommonDataClass.DataClass import *\r
-from String import *\r
+from StringUtils import *\r
 from DataType import *\r
 \r
 from Table.TableDataModel import TableDataModel\r
 from DataType import *\r
 \r
 from Table.TableDataModel import TableDataModel\r
index 453c2039e3d9a71b4058f70838dfe59b6e6afa4a..527852a50c09ed57ee3c96e6e459ff6ac8923102 100644 (file)
@@ -14,7 +14,7 @@
 ##\r
 # Import Modules\r
 #\r
 ##\r
 # Import Modules\r
 #\r
-from String import *\r
+from StringUtils import *\r
 from CommonDataClass.DataClass import *\r
 from DataType import *\r
 \r
 from CommonDataClass.DataClass import *\r
 from DataType import *\r
 \r
diff --git a/BaseTools/Source/Python/Common/String.py b/BaseTools/Source/Python/Common/String.py
deleted file mode 100644 (file)
index 34361ec..0000000
+++ /dev/null
@@ -1,885 +0,0 @@
-## @file\r
-# This file is used to define common string related functions used in parsing process\r
-#\r
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this 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
-# Import Modules\r
-#\r
-import re\r
-import DataType\r
-import Common.LongFilePathOs as os\r
-import string\r
-import EdkLogger as EdkLogger\r
-\r
-import GlobalData\r
-from BuildToolError import *\r
-from CommonDataClass.Exceptions import *\r
-from Common.LongFilePathSupport import OpenLongFilePath as open\r
-from Common.MultipleWorkspace import MultipleWorkspace as mws\r
-\r
-gHexVerPatt = re.compile('0x[a-f0-9]{4}[a-f0-9]{4}$', re.IGNORECASE)\r
-gHumanReadableVerPatt = re.compile(r'([1-9][0-9]*|0)\.[0-9]{1,2}$')\r
-\r
-## GetSplitValueList\r
-#\r
-# Get a value list from a string with multiple values splited with SplitTag\r
-# The default SplitTag is DataType.TAB_VALUE_SPLIT\r
-# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']\r
-#\r
-# @param String:    The input string to be splitted\r
-# @param SplitTag:  The split key, default is DataType.TAB_VALUE_SPLIT\r
-# @param MaxSplit:  The max number of split values, default is -1\r
-#\r
-# @retval list() A list for splitted string\r
-#\r
-def GetSplitValueList(String, SplitTag=DataType.TAB_VALUE_SPLIT, MaxSplit= -1):\r
-    ValueList = []\r
-    Last = 0\r
-    Escaped = False\r
-    InSingleQuoteString = False\r
-    InDoubleQuoteString = False\r
-    InParenthesis = 0\r
-    for Index in range(0, len(String)):\r
-        Char = String[Index]\r
-\r
-        if not Escaped:\r
-            # Found a splitter not in a string, split it\r
-            if (not InSingleQuoteString or not InDoubleQuoteString) and InParenthesis == 0 and Char == SplitTag:\r
-                ValueList.append(String[Last:Index].strip())\r
-                Last = Index + 1\r
-                if MaxSplit > 0 and len(ValueList) >= MaxSplit:\r
-                    break\r
-\r
-            if Char == '\\' and (InSingleQuoteString or InDoubleQuoteString):\r
-                Escaped = True\r
-            elif Char == '"' and not InSingleQuoteString:\r
-                if not InDoubleQuoteString:\r
-                    InDoubleQuoteString = True\r
-                else:\r
-                    InDoubleQuoteString = False\r
-            elif Char == "'" and not InDoubleQuoteString:\r
-                if not InSingleQuoteString:\r
-                    InSingleQuoteString = True\r
-                else:\r
-                    InSingleQuoteString = False\r
-            elif Char == '(':\r
-                InParenthesis = InParenthesis + 1\r
-            elif Char == ')':\r
-                InParenthesis = InParenthesis - 1\r
-        else:\r
-            Escaped = False\r
-\r
-    if Last < len(String):\r
-        ValueList.append(String[Last:].strip())\r
-    elif Last == len(String):\r
-        ValueList.append('')\r
-\r
-    return ValueList\r
-\r
-## GetSplitList\r
-#\r
-# Get a value list from a string with multiple values splited with SplitString\r
-# The default SplitTag is DataType.TAB_VALUE_SPLIT\r
-# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']\r
-#\r
-# @param String:    The input string to be splitted\r
-# @param SplitStr:  The split key, default is DataType.TAB_VALUE_SPLIT\r
-# @param MaxSplit:  The max number of split values, default is -1\r
-#\r
-# @retval list() A list for splitted string\r
-#\r
-def GetSplitList(String, SplitStr=DataType.TAB_VALUE_SPLIT, MaxSplit= -1):\r
-    return map(lambda l: l.strip(), String.split(SplitStr, MaxSplit))\r
-\r
-## MergeArches\r
-#\r
-# Find a key's all arches in dict, add the new arch to the list\r
-# If not exist any arch, set the arch directly\r
-#\r
-# @param Dict:  The input value for Dict\r
-# @param Key:   The input value for Key\r
-# @param Arch:  The Arch to be added or merged\r
-#\r
-def MergeArches(Dict, Key, Arch):\r
-    if Key in Dict:\r
-        Dict[Key].append(Arch)\r
-    else:\r
-        Dict[Key] = Arch.split()\r
-\r
-## GenDefines\r
-#\r
-# Parse a string with format "DEFINE <VarName> = <PATH>"\r
-# Generate a map Defines[VarName] = PATH\r
-# Return False if invalid format\r
-#\r
-# @param String:   String with DEFINE statement\r
-# @param Arch:     Supportted Arch\r
-# @param Defines:  DEFINE statement to be parsed\r
-#\r
-# @retval 0   DEFINE statement found, and valid\r
-# @retval 1   DEFINE statement found, but not valid\r
-# @retval -1  DEFINE statement not found\r
-#\r
-def GenDefines(String, Arch, Defines):\r
-    if String.find(DataType.TAB_DEFINE + ' ') > -1:\r
-        List = String.replace(DataType.TAB_DEFINE + ' ', '').split(DataType.TAB_EQUAL_SPLIT)\r
-        if len(List) == 2:\r
-            Defines[(CleanString(List[0]), Arch)] = CleanString(List[1])\r
-            return 0\r
-        else:\r
-            return -1\r
-\r
-    return 1\r
-\r
-## GenInclude\r
-#\r
-# Parse a string with format "!include <Filename>"\r
-# Return the file path\r
-# Return False if invalid format or NOT FOUND\r
-#\r
-# @param String:        String with INCLUDE statement\r
-# @param IncludeFiles:  INCLUDE statement to be parsed\r
-# @param Arch:          Supportted Arch\r
-#\r
-# @retval True\r
-# @retval False\r
-#\r
-def GenInclude(String, IncludeFiles, Arch):\r
-    if String.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1:\r
-        IncludeFile = CleanString(String[String.upper().find(DataType.TAB_INCLUDE.upper() + ' ') + len(DataType.TAB_INCLUDE + ' ') : ])\r
-        MergeArches(IncludeFiles, IncludeFile, Arch)\r
-        return True\r
-    else:\r
-        return False\r
-\r
-## GetLibraryClassesWithModuleType\r
-#\r
-# Get Library Class definition when no module type defined\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 library classes successfully\r
-#\r
-def GetLibraryClassesWithModuleType(Lines, Key, KeyValues, CommentCharacter):\r
-    newKey = SplitModuleType(Key)\r
-    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
-    LineList = Lines.splitlines()\r
-    for Line in LineList:\r
-        Line = CleanString(Line, CommentCharacter)\r
-        if Line != '' and Line[0] != CommentCharacter:\r
-            KeyValues.append([CleanString(Line, CommentCharacter), newKey[1]])\r
-\r
-    return True\r
-\r
-## GetDynamics\r
-#\r
-# Get Dynamic Pcds\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 Dynamic Pcds successfully\r
-#\r
-def GetDynamics(Lines, Key, KeyValues, CommentCharacter):\r
-    #\r
-    # Get SkuId Name List\r
-    #\r
-    SkuIdNameList = SplitModuleType(Key)\r
-\r
-    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
-    LineList = Lines.splitlines()\r
-    for Line in LineList:\r
-        Line = CleanString(Line, CommentCharacter)\r
-        if Line != '' and Line[0] != CommentCharacter:\r
-            KeyValues.append([CleanString(Line, CommentCharacter), SkuIdNameList[1]])\r
-\r
-    return True\r
-\r
-## SplitModuleType\r
-#\r
-# Split ModuleType out of section defien to get key\r
-# [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [ 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]\r
-#\r
-# @param Key:  String to be parsed\r
-#\r
-# @retval ReturnValue A list for module types\r
-#\r
-def SplitModuleType(Key):\r
-    KeyList = Key.split(DataType.TAB_SPLIT)\r
-    #\r
-    # Fill in for arch\r
-    #\r
-    KeyList.append('')\r
-    #\r
-    # Fill in for moduletype\r
-    #\r
-    KeyList.append('')\r
-    ReturnValue = []\r
-    KeyValue = KeyList[0]\r
-    if KeyList[1] != '':\r
-        KeyValue = KeyValue + DataType.TAB_SPLIT + KeyList[1]\r
-    ReturnValue.append(KeyValue)\r
-    ReturnValue.append(GetSplitValueList(KeyList[2]))\r
-\r
-    return ReturnValue\r
-\r
-## Replace macro in strings list\r
-#\r
-# This method replace macros used in a given string list. The macros are\r
-# given in a dictionary.\r
-#\r
-# @param StringList         StringList to be processed\r
-# @param MacroDefinitions   The macro definitions in the form of dictionary\r
-# @param SelfReplacement    To decide whether replace un-defined macro to ''\r
-#\r
-# @retval NewList           A new string list whose macros are replaced\r
-#\r
-def ReplaceMacros(StringList, MacroDefinitions={}, SelfReplacement=False):\r
-    NewList = []\r
-    for String in StringList:\r
-        if type(String) == type(''):\r
-            NewList.append(ReplaceMacro(String, MacroDefinitions, SelfReplacement))\r
-        else:\r
-            NewList.append(String)\r
-\r
-    return NewList\r
-\r
-## Replace macro in string\r
-#\r
-# This method replace macros used in given string. The macros are given in a\r
-# dictionary.\r
-#\r
-# @param String             String to be processed\r
-# @param MacroDefinitions   The macro definitions in the form of dictionary\r
-# @param SelfReplacement    To decide whether replace un-defined macro to ''\r
-#\r
-# @retval string            The string whose macros are replaced\r
-#\r
-def ReplaceMacro(String, MacroDefinitions={}, SelfReplacement=False, RaiseError=False):\r
-    LastString = String\r
-    while String and MacroDefinitions:\r
-        MacroUsed = GlobalData.gMacroRefPattern.findall(String)\r
-        # no macro found in String, stop replacing\r
-        if len(MacroUsed) == 0:\r
-            break\r
-\r
-        for Macro in MacroUsed:\r
-            if Macro not in MacroDefinitions:\r
-                if RaiseError:\r
-                    raise SymbolNotFound("%s not defined" % Macro)\r
-                if SelfReplacement:\r
-                    String = String.replace("$(%s)" % Macro, '')\r
-                continue\r
-            if "$(%s)" % Macro not in MacroDefinitions[Macro]:\r
-                String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro])\r
-        # in case there's macro not defined\r
-        if String == LastString:\r
-            break\r
-        LastString = String\r
-\r
-    return String\r
-\r
-## NormPath\r
-#\r
-# Create a normal path\r
-# And replace DFEINE in the path\r
-#\r
-# @param Path:     The input value for Path to be converted\r
-# @param Defines:  A set for DEFINE statement\r
-#\r
-# @retval Path Formatted path\r
-#\r
-def NormPath(Path, Defines={}):\r
-    IsRelativePath = False\r
-    if Path:\r
-        if Path[0] == '.':\r
-            IsRelativePath = True\r
-        #\r
-        # Replace with Define\r
-        #\r
-        if Defines:\r
-            Path = ReplaceMacro(Path, Defines)\r
-        #\r
-        # To local path format\r
-        #\r
-        Path = os.path.normpath(Path)\r
-        if Path.startswith(GlobalData.gWorkspace) and not Path.startswith(GlobalData.gBuildDirectory) and not os.path.exists(Path):\r
-            Path = Path[len (GlobalData.gWorkspace):]\r
-            if Path[0] == os.path.sep:\r
-                Path = Path[1:]\r
-            Path = mws.join(GlobalData.gWorkspace, Path)\r
-\r
-    if IsRelativePath and Path[0] != '.':\r
-        Path = os.path.join('.', Path)\r
-\r
-    return Path\r
-\r
-## CleanString\r
-#\r
-# Remove comments in a string\r
-# Remove spaces\r
-#\r
-# @param Line:              The string to be cleaned\r
-# @param CommentCharacter:  Comment char, used to ignore comment content, default is DataType.TAB_COMMENT_SPLIT\r
-#\r
-# @retval Path Formatted path\r
-#\r
-def CleanString(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False, BuildOption=False):\r
-    #\r
-    # remove whitespace\r
-    #\r
-    Line = Line.strip();\r
-    #\r
-    # Replace Edk's comment character\r
-    #\r
-    if AllowCppStyleComment:\r
-        Line = Line.replace(DataType.TAB_COMMENT_EDK_SPLIT, CommentCharacter)\r
-    #\r
-    # remove comments, but we should escape comment character in string\r
-    #\r
-    InDoubleQuoteString = False\r
-    InSingleQuoteString = False\r
-    CommentInString = False\r
-    for Index in range(0, len(Line)):\r
-        if Line[Index] == '"' and not InSingleQuoteString:\r
-            InDoubleQuoteString = not InDoubleQuoteString\r
-        elif Line[Index] == "'" and not InDoubleQuoteString:\r
-            InSingleQuoteString = not InSingleQuoteString\r
-        elif Line[Index] == CommentCharacter and (InSingleQuoteString or InDoubleQuoteString):\r
-            CommentInString = True\r
-        elif Line[Index] == CommentCharacter and not (InSingleQuoteString or InDoubleQuoteString):\r
-            Line = Line[0: Index]\r
-            break\r
-\r
-    if CommentInString and BuildOption:\r
-        Line = Line.replace('"', '')\r
-        ChIndex = Line.find('#')\r
-        while ChIndex >= 0:\r
-            if GlobalData.gIsWindows:\r
-                if ChIndex == 0 or Line[ChIndex - 1] != '^':\r
-                    Line = Line[0:ChIndex] + '^' + Line[ChIndex:]\r
-                    ChIndex = Line.find('#', ChIndex + 2)\r
-                else:\r
-                    ChIndex = Line.find('#', ChIndex + 1)\r
-            else:\r
-                if ChIndex == 0 or Line[ChIndex - 1] != '\\':\r
-                    Line = Line[0:ChIndex] + '\\' + Line[ChIndex:]\r
-                    ChIndex = Line.find('#', ChIndex + 2)\r
-                else:\r
-                    ChIndex = Line.find('#', ChIndex + 1)\r
-    #\r
-    # remove whitespace again\r
-    #\r
-    Line = Line.strip();\r
-\r
-    return Line\r
-\r
-## CleanString2\r
-#\r
-# Split statement with comments in a string\r
-# Remove spaces\r
-#\r
-# @param Line:              The string to be cleaned\r
-# @param CommentCharacter:  Comment char, used to ignore comment content, default is DataType.TAB_COMMENT_SPLIT\r
-#\r
-# @retval Path Formatted path\r
-#\r
-def CleanString2(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):\r
-    #\r
-    # remove whitespace\r
-    #\r
-    Line = Line.strip();\r
-    #\r
-    # Replace Edk's comment character\r
-    #\r
-    if AllowCppStyleComment:\r
-        Line = Line.replace(DataType.TAB_COMMENT_EDK_SPLIT, CommentCharacter)\r
-    #\r
-    # separate comments and statements, but we should escape comment character in string\r
-    #\r
-    InDoubleQuoteString = False\r
-    InSingleQuoteString = False\r
-    CommentInString = False\r
-    Comment = ''\r
-    for Index in range(0, len(Line)):\r
-        if Line[Index] == '"' and not InSingleQuoteString:\r
-            InDoubleQuoteString = not InDoubleQuoteString\r
-        elif Line[Index] == "'" and not InDoubleQuoteString:\r
-            InSingleQuoteString = not InSingleQuoteString\r
-        elif Line[Index] == CommentCharacter and (InDoubleQuoteString or InSingleQuoteString):\r
-            CommentInString = True\r
-        elif Line[Index] == CommentCharacter and not (InDoubleQuoteString or InSingleQuoteString):\r
-            Comment = Line[Index:].strip()\r
-            Line = Line[0:Index].strip()\r
-            break\r
-\r
-    return Line, Comment\r
-\r
-## GetMultipleValuesOfKeyFromLines\r
-#\r
-# Parse multiple strings to clean comment and spaces\r
-# The result is saved to KeyValues\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 Successfully executed\r
-#\r
-def GetMultipleValuesOfKeyFromLines(Lines, Key, KeyValues, CommentCharacter):\r
-    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
-    LineList = Lines.split('\n')\r
-    for Line in LineList:\r
-        Line = CleanString(Line, CommentCharacter)\r
-        if Line != '' and Line[0] != CommentCharacter:\r
-            KeyValues += [Line]\r
-\r
-    return True\r
-\r
-## GetDefineValue\r
-#\r
-# Parse a DEFINE statement to get defined value\r
-# DEFINE Key Value\r
-#\r
-# @param String:            The content to be parsed\r
-# @param Key:               The key of DEFINE statement\r
-# @param CommentCharacter:  Comment char, used to ignore comment content\r
-#\r
-# @retval string The defined value\r
-#\r
-def GetDefineValue(String, Key, CommentCharacter):\r
-    String = CleanString(String)\r
-    return String[String.find(Key + ' ') + len(Key + ' ') : ]\r
-\r
-## GetHexVerValue\r
-#\r
-# Get a Hex Version Value\r
-#\r
-# @param VerString:         The version string to be parsed\r
-#\r
-#\r
-# @retval:      If VerString is incorrectly formatted, return "None" which will break the build.\r
-#               If VerString is correctly formatted, return a Hex value of the Version Number (0xmmmmnnnn)\r
-#                   where mmmm is the major number and nnnn is the adjusted minor number.\r
-#\r
-def GetHexVerValue(VerString):\r
-    VerString = CleanString(VerString)\r
-\r
-    if gHumanReadableVerPatt.match(VerString):\r
-        ValueList = VerString.split('.')\r
-        Major = ValueList[0]\r
-        Minor = ValueList[1]\r
-        if len(Minor) == 1:\r
-            Minor += '0'\r
-        DeciValue = (int(Major) << 16) + int(Minor);\r
-        return "0x%08x" % DeciValue\r
-    elif gHexVerPatt.match(VerString):\r
-        return VerString\r
-    else:\r
-        return None\r
-\r
-\r
-## GetSingleValueOfKeyFromLines\r
-#\r
-# Parse multiple strings as below to get value of each definition line\r
-# Key1 = Value1\r
-# Key2 = Value2\r
-# The result is saved to Dictionary\r
-#\r
-# @param Lines:                The content to be parsed\r
-# @param Dictionary:           To store data after parsing\r
-# @param CommentCharacter:     Comment char, be used to ignore comment content\r
-# @param KeySplitCharacter:    Key split char, between key name and key value. Key1 = Value1, '=' is the key split char\r
-# @param ValueSplitFlag:       Value split flag, be used to decide if has multiple values\r
-# @param ValueSplitCharacter:  Value split char, be used to split multiple values. Key1 = Value1|Value2, '|' is the value split char\r
-#\r
-# @retval True Successfully executed\r
-#\r
-def GetSingleValueOfKeyFromLines(Lines, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter):\r
-    Lines = Lines.split('\n')\r
-    Keys = []\r
-    Value = ''\r
-    DefineValues = ['']\r
-    SpecValues = ['']\r
-\r
-    for Line in Lines:\r
-        #\r
-        # Handle DEFINE and SPEC\r
-        #\r
-        if Line.find(DataType.TAB_INF_DEFINES_DEFINE + ' ') > -1:\r
-            if '' in DefineValues:\r
-                DefineValues.remove('')\r
-            DefineValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_DEFINE, CommentCharacter))\r
-            continue\r
-        if Line.find(DataType.TAB_INF_DEFINES_SPEC + ' ') > -1:\r
-            if '' in SpecValues:\r
-                SpecValues.remove('')\r
-            SpecValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_SPEC, CommentCharacter))\r
-            continue\r
-\r
-        #\r
-        # Handle Others\r
-        #\r
-        LineList = Line.split(KeySplitCharacter, 1)\r
-        if len(LineList) >= 2:\r
-            Key = LineList[0].split()\r
-            if len(Key) == 1 and Key[0][0] != CommentCharacter:\r
-                #\r
-                # Remove comments and white spaces\r
-                #\r
-                LineList[1] = CleanString(LineList[1], CommentCharacter)\r
-                if ValueSplitFlag:\r
-                    Value = map(string.strip, LineList[1].split(ValueSplitCharacter))\r
-                else:\r
-                    Value = CleanString(LineList[1], CommentCharacter).splitlines()\r
-\r
-                if Key[0] in Dictionary:\r
-                    if Key[0] not in Keys:\r
-                        Dictionary[Key[0]] = Value\r
-                        Keys.append(Key[0])\r
-                    else:\r
-                        Dictionary[Key[0]].extend(Value)\r
-                else:\r
-                    Dictionary[DataType.TAB_INF_DEFINES_MACRO][Key[0]] = Value[0]\r
-\r
-    if DefineValues == []:\r
-        DefineValues = ['']\r
-    if SpecValues == []:\r
-        SpecValues = ['']\r
-    Dictionary[DataType.TAB_INF_DEFINES_DEFINE] = DefineValues\r
-    Dictionary[DataType.TAB_INF_DEFINES_SPEC] = SpecValues\r
-\r
-    return True\r
-\r
-## The content to be parsed\r
-#\r
-# Do pre-check for a file before it is parsed\r
-# Check $()\r
-# Check []\r
-#\r
-# @param FileName:       Used for error report\r
-# @param FileContent:    File content to be parsed\r
-# @param SupSectionTag:  Used for error report\r
-#\r
-def PreCheck(FileName, FileContent, SupSectionTag):\r
-    LineNo = 0\r
-    IsFailed = False\r
-    NewFileContent = ''\r
-    for Line in FileContent.splitlines():\r
-        LineNo = LineNo + 1\r
-        #\r
-        # Clean current line\r
-        #\r
-        Line = CleanString(Line)\r
-\r
-        #\r
-        # Remove commented line\r
-        #\r
-        if Line.find(DataType.TAB_COMMA_SPLIT) == 0:\r
-            Line = ''\r
-        #\r
-        # Check $()\r
-        #\r
-        if Line.find('$') > -1:\r
-            if Line.find('$(') < 0 or Line.find(')') < 0:\r
-                EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)\r
-\r
-        #\r
-        # Check []\r
-        #\r
-        if Line.find('[') > -1 or Line.find(']') > -1:\r
-            #\r
-            # Only get one '[' or one ']'\r
-            #\r
-            if not (Line.find('[') > -1 and Line.find(']') > -1):\r
-                EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)\r
-\r
-        #\r
-        # Regenerate FileContent\r
-        #\r
-        NewFileContent = NewFileContent + Line + '\r\n'\r
-\r
-    if IsFailed:\r
-       EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)\r
-\r
-    return NewFileContent\r
-\r
-## CheckFileType\r
-#\r
-# Check if the Filename is including ExtName\r
-# Return True if it exists\r
-# Raise a error message if it not exists\r
-#\r
-# @param CheckFilename:      Name of the file to be checked\r
-# @param ExtName:            Ext name of the file to be checked\r
-# @param ContainerFilename:  The container file which describes the file to be checked, used for error report\r
-# @param SectionName:        Used for error report\r
-# @param Line:               The line in container file which defines the file to be checked\r
-#\r
-# @retval True The file type is correct\r
-#\r
-def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo= -1):\r
-    if CheckFilename != '' and CheckFilename is not None:\r
-        (Root, Ext) = os.path.splitext(CheckFilename)\r
-        if Ext.upper() != ExtName.upper():\r
-            ContainerFile = open(ContainerFilename, 'r').read()\r
-            if LineNo == -1:\r
-                LineNo = GetLineNo(ContainerFile, Line)\r
-            ErrorMsg = "Invalid %s. '%s' is found, but '%s' file is needed" % (SectionName, CheckFilename, ExtName)\r
-            EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, Line=LineNo,\r
-                            File=ContainerFilename, RaiseError=EdkLogger.IsRaiseError)\r
-\r
-    return True\r
-\r
-## CheckFileExist\r
-#\r
-# Check if the file exists\r
-# Return True if it exists\r
-# Raise a error message if it not exists\r
-#\r
-# @param CheckFilename:      Name of the file to be checked\r
-# @param WorkspaceDir:       Current workspace dir\r
-# @param ContainerFilename:  The container file which describes the file to be checked, used for error report\r
-# @param SectionName:        Used for error report\r
-# @param Line:               The line in container file which defines the file to be checked\r
-#\r
-# @retval The file full path if the file exists\r
-#\r
-def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo= -1):\r
-    CheckFile = ''\r
-    if CheckFilename != '' and CheckFilename is not None:\r
-        CheckFile = WorkspaceFile(WorkspaceDir, CheckFilename)\r
-        if not os.path.isfile(CheckFile):\r
-            ContainerFile = open(ContainerFilename, 'r').read()\r
-            if LineNo == -1:\r
-                LineNo = GetLineNo(ContainerFile, Line)\r
-            ErrorMsg = "Can't find file '%s' defined in section '%s'" % (CheckFile, SectionName)\r
-            EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg,\r
-                            File=ContainerFilename, Line=LineNo, RaiseError=EdkLogger.IsRaiseError)\r
-\r
-    return CheckFile\r
-\r
-## GetLineNo\r
-#\r
-# Find the index of a line in a file\r
-#\r
-# @param FileContent:  Search scope\r
-# @param Line:         Search key\r
-#\r
-# @retval int  Index of the line\r
-# @retval -1     The line is not found\r
-#\r
-def GetLineNo(FileContent, Line, IsIgnoreComment=True):\r
-    LineList = FileContent.splitlines()\r
-    for Index in range(len(LineList)):\r
-        if LineList[Index].find(Line) > -1:\r
-            #\r
-            # Ignore statement in comment\r
-            #\r
-            if IsIgnoreComment:\r
-                if LineList[Index].strip()[0] == DataType.TAB_COMMENT_SPLIT:\r
-                    continue\r
-            return Index + 1\r
-\r
-    return -1\r
-\r
-## RaiseParserError\r
-#\r
-# Raise a parser error\r
-#\r
-# @param Line:     String which has error\r
-# @param Section:  Used for error report\r
-# @param File:     File which has the string\r
-# @param Format:   Correct format\r
-#\r
-def RaiseParserError(Line, Section, File, Format='', LineNo= -1):\r
-    if LineNo == -1:\r
-        LineNo = GetLineNo(open(os.path.normpath(File), 'r').read(), Line)\r
-    ErrorMsg = "Invalid statement '%s' is found in section '%s'" % (Line, Section)\r
-    if Format != '':\r
-        Format = "Correct format is " + Format\r
-    EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=File, Line=LineNo, ExtraData=Format, RaiseError=EdkLogger.IsRaiseError)\r
-\r
-## WorkspaceFile\r
-#\r
-# Return a full path with workspace dir\r
-#\r
-# @param WorkspaceDir:  Workspace dir\r
-# @param Filename:      Relative file name\r
-#\r
-# @retval string A full path\r
-#\r
-def WorkspaceFile(WorkspaceDir, Filename):\r
-    return mws.join(NormPath(WorkspaceDir), NormPath(Filename))\r
-\r
-## Split string\r
-#\r
-# Revmove '"' which startswith and endswith string\r
-#\r
-# @param String:  The string need to be splited\r
-#\r
-# @retval String: The string after removed '""'\r
-#\r
-def SplitString(String):\r
-    if String.startswith('\"'):\r
-        String = String[1:]\r
-    if String.endswith('\"'):\r
-        String = String[:-1]\r
-\r
-    return String\r
-\r
-## Convert To Sql String\r
-#\r
-# 1. Replace "'" with "''" in each item of StringList\r
-#\r
-# @param StringList:  A list for strings to be converted\r
-#\r
-def ConvertToSqlString(StringList):\r
-    return map(lambda s: s.replace("'", "''") , StringList)\r
-\r
-## Convert To Sql String\r
-#\r
-# 1. Replace "'" with "''" in the String\r
-#\r
-# @param String:  A String to be converted\r
-#\r
-def ConvertToSqlString2(String):\r
-    return String.replace("'", "''")\r
-\r
-#\r
-# Remove comment block\r
-#\r
-def RemoveBlockComment(Lines):\r
-    IsFindBlockComment = False\r
-    IsFindBlockCode = False\r
-    ReservedLine = ''\r
-    NewLines = []\r
-\r
-    for Line in Lines:\r
-        Line = Line.strip()\r
-        #\r
-        # Remove comment block\r
-        #\r
-        if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:\r
-            ReservedLine = GetSplitList(Line, DataType.TAB_COMMENT_EDK_START, 1)[0]\r
-            IsFindBlockComment = True\r
-        if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:\r
-            Line = ReservedLine + GetSplitList(Line, DataType.TAB_COMMENT_EDK_END, 1)[1]\r
-            ReservedLine = ''\r
-            IsFindBlockComment = False\r
-        if IsFindBlockComment:\r
-            NewLines.append('')\r
-            continue\r
-\r
-        NewLines.append(Line)\r
-    return NewLines\r
-\r
-#\r
-# Get String of a List\r
-#\r
-def GetStringOfList(List, Split=' '):\r
-    if type(List) != type([]):\r
-        return List\r
-    Str = ''\r
-    for Item in List:\r
-        Str = Str + Item + Split\r
-\r
-    return Str.strip()\r
-\r
-#\r
-# Get HelpTextList from HelpTextClassList\r
-#\r
-def GetHelpTextList(HelpTextClassList):\r
-    List = []\r
-    if HelpTextClassList:\r
-        for HelpText in HelpTextClassList:\r
-            if HelpText.String.endswith('\n'):\r
-                HelpText.String = HelpText.String[0: len(HelpText.String) - len('\n')]\r
-                List.extend(HelpText.String.split('\n'))\r
-\r
-    return List\r
-\r
-def StringToArray(String):\r
-    if isinstance(String, unicode):\r
-        if len(unicode) == 0:\r
-            return "{0x00,0x00}"\r
-        return "{%s,0x00,0x00}" % ",".join("0x%02x,0x00" % ord(C) for C in String)\r
-    elif String.startswith('L"'):\r
-        if String == "L\"\"":\r
-            return "{0x00,0x00}"\r
-        else:\r
-            return "{%s,0x00,0x00}" % ",".join("0x%02x,0x00" % ord(C) for C in String[2:-1])\r
-    elif String.startswith('"'):\r
-        if String == "\"\"":\r
-            return "{0x00,0x00}"\r
-        else:\r
-            StringLen = len(String[1:-1])\r
-            if StringLen % 2:\r
-                return "{%s,0x00}" % ",".join("0x%02x" % ord(C) for C in String[1:-1])\r
-            else:\r
-                return "{%s,0x00,0x00}" % ",".join("0x%02x" % ord(C) for C in String[1:-1])\r
-    elif String.startswith('{'):\r
-        StringLen = len(String.split(","))\r
-        if StringLen % 2:\r
-            return "{%s,0x00}" % ",".join(C.strip() for C in String[1:-1].split(','))\r
-        else:\r
-            return "{%s}" % ",".join(C.strip() for C in String[1:-1].split(','))\r
-        \r
-    else:\r
-        if len(String.split()) % 2:\r
-            return '{%s,0}' % ','.join(String.split())\r
-        else:\r
-            return '{%s,0,0}' % ','.join(String.split())\r
-\r
-def StringArrayLength(String):\r
-    if isinstance(String, unicode):\r
-        return (len(String) + 1) * 2 + 1;\r
-    elif String.startswith('L"'):\r
-        return (len(String) - 3 + 1) * 2\r
-    elif String.startswith('"'):\r
-        return (len(String) - 2 + 1)\r
-    else:\r
-        return len(String.split()) + 1\r
-\r
-def RemoveDupOption(OptionString, Which="/I", Against=None):\r
-    OptionList = OptionString.split()\r
-    ValueList = []\r
-    if Against:\r
-        ValueList += Against\r
-    for Index in range(len(OptionList)):\r
-        Opt = OptionList[Index]\r
-        if not Opt.startswith(Which):\r
-            continue\r
-        if len(Opt) > len(Which):\r
-            Val = Opt[len(Which):]\r
-        else:\r
-            Val = ""\r
-        if Val in ValueList:\r
-            OptionList[Index] = ""\r
-        else:\r
-            ValueList.append(Val)\r
-    return " ".join(OptionList)\r
-\r
-##\r
-#\r
-# This acts like the main() function for the script, unless it is 'import'ed into another\r
-# script.\r
-#\r
-if __name__ == '__main__':\r
-    pass\r
-\r
diff --git a/BaseTools/Source/Python/Common/StringUtils.py b/BaseTools/Source/Python/Common/StringUtils.py
new file mode 100644 (file)
index 0000000..34361ec
--- /dev/null
@@ -0,0 +1,885 @@
+## @file\r
+# This file is used to define common string related functions used in parsing process\r
+#\r
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this 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
+# Import Modules\r
+#\r
+import re\r
+import DataType\r
+import Common.LongFilePathOs as os\r
+import string\r
+import EdkLogger as EdkLogger\r
+\r
+import GlobalData\r
+from BuildToolError import *\r
+from CommonDataClass.Exceptions import *\r
+from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from Common.MultipleWorkspace import MultipleWorkspace as mws\r
+\r
+gHexVerPatt = re.compile('0x[a-f0-9]{4}[a-f0-9]{4}$', re.IGNORECASE)\r
+gHumanReadableVerPatt = re.compile(r'([1-9][0-9]*|0)\.[0-9]{1,2}$')\r
+\r
+## GetSplitValueList\r
+#\r
+# Get a value list from a string with multiple values splited with SplitTag\r
+# The default SplitTag is DataType.TAB_VALUE_SPLIT\r
+# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']\r
+#\r
+# @param String:    The input string to be splitted\r
+# @param SplitTag:  The split key, default is DataType.TAB_VALUE_SPLIT\r
+# @param MaxSplit:  The max number of split values, default is -1\r
+#\r
+# @retval list() A list for splitted string\r
+#\r
+def GetSplitValueList(String, SplitTag=DataType.TAB_VALUE_SPLIT, MaxSplit= -1):\r
+    ValueList = []\r
+    Last = 0\r
+    Escaped = False\r
+    InSingleQuoteString = False\r
+    InDoubleQuoteString = False\r
+    InParenthesis = 0\r
+    for Index in range(0, len(String)):\r
+        Char = String[Index]\r
+\r
+        if not Escaped:\r
+            # Found a splitter not in a string, split it\r
+            if (not InSingleQuoteString or not InDoubleQuoteString) and InParenthesis == 0 and Char == SplitTag:\r
+                ValueList.append(String[Last:Index].strip())\r
+                Last = Index + 1\r
+                if MaxSplit > 0 and len(ValueList) >= MaxSplit:\r
+                    break\r
+\r
+            if Char == '\\' and (InSingleQuoteString or InDoubleQuoteString):\r
+                Escaped = True\r
+            elif Char == '"' and not InSingleQuoteString:\r
+                if not InDoubleQuoteString:\r
+                    InDoubleQuoteString = True\r
+                else:\r
+                    InDoubleQuoteString = False\r
+            elif Char == "'" and not InDoubleQuoteString:\r
+                if not InSingleQuoteString:\r
+                    InSingleQuoteString = True\r
+                else:\r
+                    InSingleQuoteString = False\r
+            elif Char == '(':\r
+                InParenthesis = InParenthesis + 1\r
+            elif Char == ')':\r
+                InParenthesis = InParenthesis - 1\r
+        else:\r
+            Escaped = False\r
+\r
+    if Last < len(String):\r
+        ValueList.append(String[Last:].strip())\r
+    elif Last == len(String):\r
+        ValueList.append('')\r
+\r
+    return ValueList\r
+\r
+## GetSplitList\r
+#\r
+# Get a value list from a string with multiple values splited with SplitString\r
+# The default SplitTag is DataType.TAB_VALUE_SPLIT\r
+# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']\r
+#\r
+# @param String:    The input string to be splitted\r
+# @param SplitStr:  The split key, default is DataType.TAB_VALUE_SPLIT\r
+# @param MaxSplit:  The max number of split values, default is -1\r
+#\r
+# @retval list() A list for splitted string\r
+#\r
+def GetSplitList(String, SplitStr=DataType.TAB_VALUE_SPLIT, MaxSplit= -1):\r
+    return map(lambda l: l.strip(), String.split(SplitStr, MaxSplit))\r
+\r
+## MergeArches\r
+#\r
+# Find a key's all arches in dict, add the new arch to the list\r
+# If not exist any arch, set the arch directly\r
+#\r
+# @param Dict:  The input value for Dict\r
+# @param Key:   The input value for Key\r
+# @param Arch:  The Arch to be added or merged\r
+#\r
+def MergeArches(Dict, Key, Arch):\r
+    if Key in Dict:\r
+        Dict[Key].append(Arch)\r
+    else:\r
+        Dict[Key] = Arch.split()\r
+\r
+## GenDefines\r
+#\r
+# Parse a string with format "DEFINE <VarName> = <PATH>"\r
+# Generate a map Defines[VarName] = PATH\r
+# Return False if invalid format\r
+#\r
+# @param String:   String with DEFINE statement\r
+# @param Arch:     Supportted Arch\r
+# @param Defines:  DEFINE statement to be parsed\r
+#\r
+# @retval 0   DEFINE statement found, and valid\r
+# @retval 1   DEFINE statement found, but not valid\r
+# @retval -1  DEFINE statement not found\r
+#\r
+def GenDefines(String, Arch, Defines):\r
+    if String.find(DataType.TAB_DEFINE + ' ') > -1:\r
+        List = String.replace(DataType.TAB_DEFINE + ' ', '').split(DataType.TAB_EQUAL_SPLIT)\r
+        if len(List) == 2:\r
+            Defines[(CleanString(List[0]), Arch)] = CleanString(List[1])\r
+            return 0\r
+        else:\r
+            return -1\r
+\r
+    return 1\r
+\r
+## GenInclude\r
+#\r
+# Parse a string with format "!include <Filename>"\r
+# Return the file path\r
+# Return False if invalid format or NOT FOUND\r
+#\r
+# @param String:        String with INCLUDE statement\r
+# @param IncludeFiles:  INCLUDE statement to be parsed\r
+# @param Arch:          Supportted Arch\r
+#\r
+# @retval True\r
+# @retval False\r
+#\r
+def GenInclude(String, IncludeFiles, Arch):\r
+    if String.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1:\r
+        IncludeFile = CleanString(String[String.upper().find(DataType.TAB_INCLUDE.upper() + ' ') + len(DataType.TAB_INCLUDE + ' ') : ])\r
+        MergeArches(IncludeFiles, IncludeFile, Arch)\r
+        return True\r
+    else:\r
+        return False\r
+\r
+## GetLibraryClassesWithModuleType\r
+#\r
+# Get Library Class definition when no module type defined\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 library classes successfully\r
+#\r
+def GetLibraryClassesWithModuleType(Lines, Key, KeyValues, CommentCharacter):\r
+    newKey = SplitModuleType(Key)\r
+    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
+    LineList = Lines.splitlines()\r
+    for Line in LineList:\r
+        Line = CleanString(Line, CommentCharacter)\r
+        if Line != '' and Line[0] != CommentCharacter:\r
+            KeyValues.append([CleanString(Line, CommentCharacter), newKey[1]])\r
+\r
+    return True\r
+\r
+## GetDynamics\r
+#\r
+# Get Dynamic Pcds\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 Dynamic Pcds successfully\r
+#\r
+def GetDynamics(Lines, Key, KeyValues, CommentCharacter):\r
+    #\r
+    # Get SkuId Name List\r
+    #\r
+    SkuIdNameList = SplitModuleType(Key)\r
+\r
+    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
+    LineList = Lines.splitlines()\r
+    for Line in LineList:\r
+        Line = CleanString(Line, CommentCharacter)\r
+        if Line != '' and Line[0] != CommentCharacter:\r
+            KeyValues.append([CleanString(Line, CommentCharacter), SkuIdNameList[1]])\r
+\r
+    return True\r
+\r
+## SplitModuleType\r
+#\r
+# Split ModuleType out of section defien to get key\r
+# [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [ 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]\r
+#\r
+# @param Key:  String to be parsed\r
+#\r
+# @retval ReturnValue A list for module types\r
+#\r
+def SplitModuleType(Key):\r
+    KeyList = Key.split(DataType.TAB_SPLIT)\r
+    #\r
+    # Fill in for arch\r
+    #\r
+    KeyList.append('')\r
+    #\r
+    # Fill in for moduletype\r
+    #\r
+    KeyList.append('')\r
+    ReturnValue = []\r
+    KeyValue = KeyList[0]\r
+    if KeyList[1] != '':\r
+        KeyValue = KeyValue + DataType.TAB_SPLIT + KeyList[1]\r
+    ReturnValue.append(KeyValue)\r
+    ReturnValue.append(GetSplitValueList(KeyList[2]))\r
+\r
+    return ReturnValue\r
+\r
+## Replace macro in strings list\r
+#\r
+# This method replace macros used in a given string list. The macros are\r
+# given in a dictionary.\r
+#\r
+# @param StringList         StringList to be processed\r
+# @param MacroDefinitions   The macro definitions in the form of dictionary\r
+# @param SelfReplacement    To decide whether replace un-defined macro to ''\r
+#\r
+# @retval NewList           A new string list whose macros are replaced\r
+#\r
+def ReplaceMacros(StringList, MacroDefinitions={}, SelfReplacement=False):\r
+    NewList = []\r
+    for String in StringList:\r
+        if type(String) == type(''):\r
+            NewList.append(ReplaceMacro(String, MacroDefinitions, SelfReplacement))\r
+        else:\r
+            NewList.append(String)\r
+\r
+    return NewList\r
+\r
+## Replace macro in string\r
+#\r
+# This method replace macros used in given string. The macros are given in a\r
+# dictionary.\r
+#\r
+# @param String             String to be processed\r
+# @param MacroDefinitions   The macro definitions in the form of dictionary\r
+# @param SelfReplacement    To decide whether replace un-defined macro to ''\r
+#\r
+# @retval string            The string whose macros are replaced\r
+#\r
+def ReplaceMacro(String, MacroDefinitions={}, SelfReplacement=False, RaiseError=False):\r
+    LastString = String\r
+    while String and MacroDefinitions:\r
+        MacroUsed = GlobalData.gMacroRefPattern.findall(String)\r
+        # no macro found in String, stop replacing\r
+        if len(MacroUsed) == 0:\r
+            break\r
+\r
+        for Macro in MacroUsed:\r
+            if Macro not in MacroDefinitions:\r
+                if RaiseError:\r
+                    raise SymbolNotFound("%s not defined" % Macro)\r
+                if SelfReplacement:\r
+                    String = String.replace("$(%s)" % Macro, '')\r
+                continue\r
+            if "$(%s)" % Macro not in MacroDefinitions[Macro]:\r
+                String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro])\r
+        # in case there's macro not defined\r
+        if String == LastString:\r
+            break\r
+        LastString = String\r
+\r
+    return String\r
+\r
+## NormPath\r
+#\r
+# Create a normal path\r
+# And replace DFEINE in the path\r
+#\r
+# @param Path:     The input value for Path to be converted\r
+# @param Defines:  A set for DEFINE statement\r
+#\r
+# @retval Path Formatted path\r
+#\r
+def NormPath(Path, Defines={}):\r
+    IsRelativePath = False\r
+    if Path:\r
+        if Path[0] == '.':\r
+            IsRelativePath = True\r
+        #\r
+        # Replace with Define\r
+        #\r
+        if Defines:\r
+            Path = ReplaceMacro(Path, Defines)\r
+        #\r
+        # To local path format\r
+        #\r
+        Path = os.path.normpath(Path)\r
+        if Path.startswith(GlobalData.gWorkspace) and not Path.startswith(GlobalData.gBuildDirectory) and not os.path.exists(Path):\r
+            Path = Path[len (GlobalData.gWorkspace):]\r
+            if Path[0] == os.path.sep:\r
+                Path = Path[1:]\r
+            Path = mws.join(GlobalData.gWorkspace, Path)\r
+\r
+    if IsRelativePath and Path[0] != '.':\r
+        Path = os.path.join('.', Path)\r
+\r
+    return Path\r
+\r
+## CleanString\r
+#\r
+# Remove comments in a string\r
+# Remove spaces\r
+#\r
+# @param Line:              The string to be cleaned\r
+# @param CommentCharacter:  Comment char, used to ignore comment content, default is DataType.TAB_COMMENT_SPLIT\r
+#\r
+# @retval Path Formatted path\r
+#\r
+def CleanString(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False, BuildOption=False):\r
+    #\r
+    # remove whitespace\r
+    #\r
+    Line = Line.strip();\r
+    #\r
+    # Replace Edk's comment character\r
+    #\r
+    if AllowCppStyleComment:\r
+        Line = Line.replace(DataType.TAB_COMMENT_EDK_SPLIT, CommentCharacter)\r
+    #\r
+    # remove comments, but we should escape comment character in string\r
+    #\r
+    InDoubleQuoteString = False\r
+    InSingleQuoteString = False\r
+    CommentInString = False\r
+    for Index in range(0, len(Line)):\r
+        if Line[Index] == '"' and not InSingleQuoteString:\r
+            InDoubleQuoteString = not InDoubleQuoteString\r
+        elif Line[Index] == "'" and not InDoubleQuoteString:\r
+            InSingleQuoteString = not InSingleQuoteString\r
+        elif Line[Index] == CommentCharacter and (InSingleQuoteString or InDoubleQuoteString):\r
+            CommentInString = True\r
+        elif Line[Index] == CommentCharacter and not (InSingleQuoteString or InDoubleQuoteString):\r
+            Line = Line[0: Index]\r
+            break\r
+\r
+    if CommentInString and BuildOption:\r
+        Line = Line.replace('"', '')\r
+        ChIndex = Line.find('#')\r
+        while ChIndex >= 0:\r
+            if GlobalData.gIsWindows:\r
+                if ChIndex == 0 or Line[ChIndex - 1] != '^':\r
+                    Line = Line[0:ChIndex] + '^' + Line[ChIndex:]\r
+                    ChIndex = Line.find('#', ChIndex + 2)\r
+                else:\r
+                    ChIndex = Line.find('#', ChIndex + 1)\r
+            else:\r
+                if ChIndex == 0 or Line[ChIndex - 1] != '\\':\r
+                    Line = Line[0:ChIndex] + '\\' + Line[ChIndex:]\r
+                    ChIndex = Line.find('#', ChIndex + 2)\r
+                else:\r
+                    ChIndex = Line.find('#', ChIndex + 1)\r
+    #\r
+    # remove whitespace again\r
+    #\r
+    Line = Line.strip();\r
+\r
+    return Line\r
+\r
+## CleanString2\r
+#\r
+# Split statement with comments in a string\r
+# Remove spaces\r
+#\r
+# @param Line:              The string to be cleaned\r
+# @param CommentCharacter:  Comment char, used to ignore comment content, default is DataType.TAB_COMMENT_SPLIT\r
+#\r
+# @retval Path Formatted path\r
+#\r
+def CleanString2(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):\r
+    #\r
+    # remove whitespace\r
+    #\r
+    Line = Line.strip();\r
+    #\r
+    # Replace Edk's comment character\r
+    #\r
+    if AllowCppStyleComment:\r
+        Line = Line.replace(DataType.TAB_COMMENT_EDK_SPLIT, CommentCharacter)\r
+    #\r
+    # separate comments and statements, but we should escape comment character in string\r
+    #\r
+    InDoubleQuoteString = False\r
+    InSingleQuoteString = False\r
+    CommentInString = False\r
+    Comment = ''\r
+    for Index in range(0, len(Line)):\r
+        if Line[Index] == '"' and not InSingleQuoteString:\r
+            InDoubleQuoteString = not InDoubleQuoteString\r
+        elif Line[Index] == "'" and not InDoubleQuoteString:\r
+            InSingleQuoteString = not InSingleQuoteString\r
+        elif Line[Index] == CommentCharacter and (InDoubleQuoteString or InSingleQuoteString):\r
+            CommentInString = True\r
+        elif Line[Index] == CommentCharacter and not (InDoubleQuoteString or InSingleQuoteString):\r
+            Comment = Line[Index:].strip()\r
+            Line = Line[0:Index].strip()\r
+            break\r
+\r
+    return Line, Comment\r
+\r
+## GetMultipleValuesOfKeyFromLines\r
+#\r
+# Parse multiple strings to clean comment and spaces\r
+# The result is saved to KeyValues\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 Successfully executed\r
+#\r
+def GetMultipleValuesOfKeyFromLines(Lines, Key, KeyValues, CommentCharacter):\r
+    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
+    LineList = Lines.split('\n')\r
+    for Line in LineList:\r
+        Line = CleanString(Line, CommentCharacter)\r
+        if Line != '' and Line[0] != CommentCharacter:\r
+            KeyValues += [Line]\r
+\r
+    return True\r
+\r
+## GetDefineValue\r
+#\r
+# Parse a DEFINE statement to get defined value\r
+# DEFINE Key Value\r
+#\r
+# @param String:            The content to be parsed\r
+# @param Key:               The key of DEFINE statement\r
+# @param CommentCharacter:  Comment char, used to ignore comment content\r
+#\r
+# @retval string The defined value\r
+#\r
+def GetDefineValue(String, Key, CommentCharacter):\r
+    String = CleanString(String)\r
+    return String[String.find(Key + ' ') + len(Key + ' ') : ]\r
+\r
+## GetHexVerValue\r
+#\r
+# Get a Hex Version Value\r
+#\r
+# @param VerString:         The version string to be parsed\r
+#\r
+#\r
+# @retval:      If VerString is incorrectly formatted, return "None" which will break the build.\r
+#               If VerString is correctly formatted, return a Hex value of the Version Number (0xmmmmnnnn)\r
+#                   where mmmm is the major number and nnnn is the adjusted minor number.\r
+#\r
+def GetHexVerValue(VerString):\r
+    VerString = CleanString(VerString)\r
+\r
+    if gHumanReadableVerPatt.match(VerString):\r
+        ValueList = VerString.split('.')\r
+        Major = ValueList[0]\r
+        Minor = ValueList[1]\r
+        if len(Minor) == 1:\r
+            Minor += '0'\r
+        DeciValue = (int(Major) << 16) + int(Minor);\r
+        return "0x%08x" % DeciValue\r
+    elif gHexVerPatt.match(VerString):\r
+        return VerString\r
+    else:\r
+        return None\r
+\r
+\r
+## GetSingleValueOfKeyFromLines\r
+#\r
+# Parse multiple strings as below to get value of each definition line\r
+# Key1 = Value1\r
+# Key2 = Value2\r
+# The result is saved to Dictionary\r
+#\r
+# @param Lines:                The content to be parsed\r
+# @param Dictionary:           To store data after parsing\r
+# @param CommentCharacter:     Comment char, be used to ignore comment content\r
+# @param KeySplitCharacter:    Key split char, between key name and key value. Key1 = Value1, '=' is the key split char\r
+# @param ValueSplitFlag:       Value split flag, be used to decide if has multiple values\r
+# @param ValueSplitCharacter:  Value split char, be used to split multiple values. Key1 = Value1|Value2, '|' is the value split char\r
+#\r
+# @retval True Successfully executed\r
+#\r
+def GetSingleValueOfKeyFromLines(Lines, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter):\r
+    Lines = Lines.split('\n')\r
+    Keys = []\r
+    Value = ''\r
+    DefineValues = ['']\r
+    SpecValues = ['']\r
+\r
+    for Line in Lines:\r
+        #\r
+        # Handle DEFINE and SPEC\r
+        #\r
+        if Line.find(DataType.TAB_INF_DEFINES_DEFINE + ' ') > -1:\r
+            if '' in DefineValues:\r
+                DefineValues.remove('')\r
+            DefineValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_DEFINE, CommentCharacter))\r
+            continue\r
+        if Line.find(DataType.TAB_INF_DEFINES_SPEC + ' ') > -1:\r
+            if '' in SpecValues:\r
+                SpecValues.remove('')\r
+            SpecValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_SPEC, CommentCharacter))\r
+            continue\r
+\r
+        #\r
+        # Handle Others\r
+        #\r
+        LineList = Line.split(KeySplitCharacter, 1)\r
+        if len(LineList) >= 2:\r
+            Key = LineList[0].split()\r
+            if len(Key) == 1 and Key[0][0] != CommentCharacter:\r
+                #\r
+                # Remove comments and white spaces\r
+                #\r
+                LineList[1] = CleanString(LineList[1], CommentCharacter)\r
+                if ValueSplitFlag:\r
+                    Value = map(string.strip, LineList[1].split(ValueSplitCharacter))\r
+                else:\r
+                    Value = CleanString(LineList[1], CommentCharacter).splitlines()\r
+\r
+                if Key[0] in Dictionary:\r
+                    if Key[0] not in Keys:\r
+                        Dictionary[Key[0]] = Value\r
+                        Keys.append(Key[0])\r
+                    else:\r
+                        Dictionary[Key[0]].extend(Value)\r
+                else:\r
+                    Dictionary[DataType.TAB_INF_DEFINES_MACRO][Key[0]] = Value[0]\r
+\r
+    if DefineValues == []:\r
+        DefineValues = ['']\r
+    if SpecValues == []:\r
+        SpecValues = ['']\r
+    Dictionary[DataType.TAB_INF_DEFINES_DEFINE] = DefineValues\r
+    Dictionary[DataType.TAB_INF_DEFINES_SPEC] = SpecValues\r
+\r
+    return True\r
+\r
+## The content to be parsed\r
+#\r
+# Do pre-check for a file before it is parsed\r
+# Check $()\r
+# Check []\r
+#\r
+# @param FileName:       Used for error report\r
+# @param FileContent:    File content to be parsed\r
+# @param SupSectionTag:  Used for error report\r
+#\r
+def PreCheck(FileName, FileContent, SupSectionTag):\r
+    LineNo = 0\r
+    IsFailed = False\r
+    NewFileContent = ''\r
+    for Line in FileContent.splitlines():\r
+        LineNo = LineNo + 1\r
+        #\r
+        # Clean current line\r
+        #\r
+        Line = CleanString(Line)\r
+\r
+        #\r
+        # Remove commented line\r
+        #\r
+        if Line.find(DataType.TAB_COMMA_SPLIT) == 0:\r
+            Line = ''\r
+        #\r
+        # Check $()\r
+        #\r
+        if Line.find('$') > -1:\r
+            if Line.find('$(') < 0 or Line.find(')') < 0:\r
+                EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)\r
+\r
+        #\r
+        # Check []\r
+        #\r
+        if Line.find('[') > -1 or Line.find(']') > -1:\r
+            #\r
+            # Only get one '[' or one ']'\r
+            #\r
+            if not (Line.find('[') > -1 and Line.find(']') > -1):\r
+                EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)\r
+\r
+        #\r
+        # Regenerate FileContent\r
+        #\r
+        NewFileContent = NewFileContent + Line + '\r\n'\r
+\r
+    if IsFailed:\r
+       EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)\r
+\r
+    return NewFileContent\r
+\r
+## CheckFileType\r
+#\r
+# Check if the Filename is including ExtName\r
+# Return True if it exists\r
+# Raise a error message if it not exists\r
+#\r
+# @param CheckFilename:      Name of the file to be checked\r
+# @param ExtName:            Ext name of the file to be checked\r
+# @param ContainerFilename:  The container file which describes the file to be checked, used for error report\r
+# @param SectionName:        Used for error report\r
+# @param Line:               The line in container file which defines the file to be checked\r
+#\r
+# @retval True The file type is correct\r
+#\r
+def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo= -1):\r
+    if CheckFilename != '' and CheckFilename is not None:\r
+        (Root, Ext) = os.path.splitext(CheckFilename)\r
+        if Ext.upper() != ExtName.upper():\r
+            ContainerFile = open(ContainerFilename, 'r').read()\r
+            if LineNo == -1:\r
+                LineNo = GetLineNo(ContainerFile, Line)\r
+            ErrorMsg = "Invalid %s. '%s' is found, but '%s' file is needed" % (SectionName, CheckFilename, ExtName)\r
+            EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, Line=LineNo,\r
+                            File=ContainerFilename, RaiseError=EdkLogger.IsRaiseError)\r
+\r
+    return True\r
+\r
+## CheckFileExist\r
+#\r
+# Check if the file exists\r
+# Return True if it exists\r
+# Raise a error message if it not exists\r
+#\r
+# @param CheckFilename:      Name of the file to be checked\r
+# @param WorkspaceDir:       Current workspace dir\r
+# @param ContainerFilename:  The container file which describes the file to be checked, used for error report\r
+# @param SectionName:        Used for error report\r
+# @param Line:               The line in container file which defines the file to be checked\r
+#\r
+# @retval The file full path if the file exists\r
+#\r
+def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo= -1):\r
+    CheckFile = ''\r
+    if CheckFilename != '' and CheckFilename is not None:\r
+        CheckFile = WorkspaceFile(WorkspaceDir, CheckFilename)\r
+        if not os.path.isfile(CheckFile):\r
+            ContainerFile = open(ContainerFilename, 'r').read()\r
+            if LineNo == -1:\r
+                LineNo = GetLineNo(ContainerFile, Line)\r
+            ErrorMsg = "Can't find file '%s' defined in section '%s'" % (CheckFile, SectionName)\r
+            EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg,\r
+                            File=ContainerFilename, Line=LineNo, RaiseError=EdkLogger.IsRaiseError)\r
+\r
+    return CheckFile\r
+\r
+## GetLineNo\r
+#\r
+# Find the index of a line in a file\r
+#\r
+# @param FileContent:  Search scope\r
+# @param Line:         Search key\r
+#\r
+# @retval int  Index of the line\r
+# @retval -1     The line is not found\r
+#\r
+def GetLineNo(FileContent, Line, IsIgnoreComment=True):\r
+    LineList = FileContent.splitlines()\r
+    for Index in range(len(LineList)):\r
+        if LineList[Index].find(Line) > -1:\r
+            #\r
+            # Ignore statement in comment\r
+            #\r
+            if IsIgnoreComment:\r
+                if LineList[Index].strip()[0] == DataType.TAB_COMMENT_SPLIT:\r
+                    continue\r
+            return Index + 1\r
+\r
+    return -1\r
+\r
+## RaiseParserError\r
+#\r
+# Raise a parser error\r
+#\r
+# @param Line:     String which has error\r
+# @param Section:  Used for error report\r
+# @param File:     File which has the string\r
+# @param Format:   Correct format\r
+#\r
+def RaiseParserError(Line, Section, File, Format='', LineNo= -1):\r
+    if LineNo == -1:\r
+        LineNo = GetLineNo(open(os.path.normpath(File), 'r').read(), Line)\r
+    ErrorMsg = "Invalid statement '%s' is found in section '%s'" % (Line, Section)\r
+    if Format != '':\r
+        Format = "Correct format is " + Format\r
+    EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=File, Line=LineNo, ExtraData=Format, RaiseError=EdkLogger.IsRaiseError)\r
+\r
+## WorkspaceFile\r
+#\r
+# Return a full path with workspace dir\r
+#\r
+# @param WorkspaceDir:  Workspace dir\r
+# @param Filename:      Relative file name\r
+#\r
+# @retval string A full path\r
+#\r
+def WorkspaceFile(WorkspaceDir, Filename):\r
+    return mws.join(NormPath(WorkspaceDir), NormPath(Filename))\r
+\r
+## Split string\r
+#\r
+# Revmove '"' which startswith and endswith string\r
+#\r
+# @param String:  The string need to be splited\r
+#\r
+# @retval String: The string after removed '""'\r
+#\r
+def SplitString(String):\r
+    if String.startswith('\"'):\r
+        String = String[1:]\r
+    if String.endswith('\"'):\r
+        String = String[:-1]\r
+\r
+    return String\r
+\r
+## Convert To Sql String\r
+#\r
+# 1. Replace "'" with "''" in each item of StringList\r
+#\r
+# @param StringList:  A list for strings to be converted\r
+#\r
+def ConvertToSqlString(StringList):\r
+    return map(lambda s: s.replace("'", "''") , StringList)\r
+\r
+## Convert To Sql String\r
+#\r
+# 1. Replace "'" with "''" in the String\r
+#\r
+# @param String:  A String to be converted\r
+#\r
+def ConvertToSqlString2(String):\r
+    return String.replace("'", "''")\r
+\r
+#\r
+# Remove comment block\r
+#\r
+def RemoveBlockComment(Lines):\r
+    IsFindBlockComment = False\r
+    IsFindBlockCode = False\r
+    ReservedLine = ''\r
+    NewLines = []\r
+\r
+    for Line in Lines:\r
+        Line = Line.strip()\r
+        #\r
+        # Remove comment block\r
+        #\r
+        if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:\r
+            ReservedLine = GetSplitList(Line, DataType.TAB_COMMENT_EDK_START, 1)[0]\r
+            IsFindBlockComment = True\r
+        if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:\r
+            Line = ReservedLine + GetSplitList(Line, DataType.TAB_COMMENT_EDK_END, 1)[1]\r
+            ReservedLine = ''\r
+            IsFindBlockComment = False\r
+        if IsFindBlockComment:\r
+            NewLines.append('')\r
+            continue\r
+\r
+        NewLines.append(Line)\r
+    return NewLines\r
+\r
+#\r
+# Get String of a List\r
+#\r
+def GetStringOfList(List, Split=' '):\r
+    if type(List) != type([]):\r
+        return List\r
+    Str = ''\r
+    for Item in List:\r
+        Str = Str + Item + Split\r
+\r
+    return Str.strip()\r
+\r
+#\r
+# Get HelpTextList from HelpTextClassList\r
+#\r
+def GetHelpTextList(HelpTextClassList):\r
+    List = []\r
+    if HelpTextClassList:\r
+        for HelpText in HelpTextClassList:\r
+            if HelpText.String.endswith('\n'):\r
+                HelpText.String = HelpText.String[0: len(HelpText.String) - len('\n')]\r
+                List.extend(HelpText.String.split('\n'))\r
+\r
+    return List\r
+\r
+def StringToArray(String):\r
+    if isinstance(String, unicode):\r
+        if len(unicode) == 0:\r
+            return "{0x00,0x00}"\r
+        return "{%s,0x00,0x00}" % ",".join("0x%02x,0x00" % ord(C) for C in String)\r
+    elif String.startswith('L"'):\r
+        if String == "L\"\"":\r
+            return "{0x00,0x00}"\r
+        else:\r
+            return "{%s,0x00,0x00}" % ",".join("0x%02x,0x00" % ord(C) for C in String[2:-1])\r
+    elif String.startswith('"'):\r
+        if String == "\"\"":\r
+            return "{0x00,0x00}"\r
+        else:\r
+            StringLen = len(String[1:-1])\r
+            if StringLen % 2:\r
+                return "{%s,0x00}" % ",".join("0x%02x" % ord(C) for C in String[1:-1])\r
+            else:\r
+                return "{%s,0x00,0x00}" % ",".join("0x%02x" % ord(C) for C in String[1:-1])\r
+    elif String.startswith('{'):\r
+        StringLen = len(String.split(","))\r
+        if StringLen % 2:\r
+            return "{%s,0x00}" % ",".join(C.strip() for C in String[1:-1].split(','))\r
+        else:\r
+            return "{%s}" % ",".join(C.strip() for C in String[1:-1].split(','))\r
+        \r
+    else:\r
+        if len(String.split()) % 2:\r
+            return '{%s,0}' % ','.join(String.split())\r
+        else:\r
+            return '{%s,0,0}' % ','.join(String.split())\r
+\r
+def StringArrayLength(String):\r
+    if isinstance(String, unicode):\r
+        return (len(String) + 1) * 2 + 1;\r
+    elif String.startswith('L"'):\r
+        return (len(String) - 3 + 1) * 2\r
+    elif String.startswith('"'):\r
+        return (len(String) - 2 + 1)\r
+    else:\r
+        return len(String.split()) + 1\r
+\r
+def RemoveDupOption(OptionString, Which="/I", Against=None):\r
+    OptionList = OptionString.split()\r
+    ValueList = []\r
+    if Against:\r
+        ValueList += Against\r
+    for Index in range(len(OptionList)):\r
+        Opt = OptionList[Index]\r
+        if not Opt.startswith(Which):\r
+            continue\r
+        if len(Opt) > len(Which):\r
+            Val = Opt[len(Which):]\r
+        else:\r
+            Val = ""\r
+        if Val in ValueList:\r
+            OptionList[Index] = ""\r
+        else:\r
+            ValueList.append(Val)\r
+    return " ".join(OptionList)\r
+\r
+##\r
+#\r
+# This acts like the main() function for the script, unless it is 'import'ed into another\r
+# script.\r
+#\r
+if __name__ == '__main__':\r
+    pass\r
+\r
index 83359586b99444c8c72744808ee1638e51325dfc..dd985ab30359adcfbf1c847a38fa7e3fa6cce373 100644 (file)
@@ -22,7 +22,7 @@ from BuildToolError import *
 from TargetTxtClassObject import *\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 from Common.Misc import PathClass\r
 from TargetTxtClassObject import *\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 from Common.Misc import PathClass\r
-from Common.String import NormPath\r
+from Common.StringUtils import NormPath\r
 import Common.GlobalData as GlobalData\r
 from Common import GlobalData\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 import Common.GlobalData as GlobalData\r
 from Common import GlobalData\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
index fee7ecb9703d18d250bf878315e77c2acca0eb68..217b60f4f319a4d6e6f4773db3fecb1ad2925128 100644 (file)
@@ -17,7 +17,7 @@
 import Common.LongFilePathOs as os\r
 import Common.EdkLogger as EdkLogger\r
 from Common.DataType import *\r
 import Common.LongFilePathOs as os\r
 import Common.EdkLogger as EdkLogger\r
 from Common.DataType import *\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 \r
 _ConfigFileToInternalTranslation = {\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 \r
 _ConfigFileToInternalTranslation = {\r
index 60dfc00260f14c99ec4175988771ae1e8a5a1312..e78d70372e36ce354be7b49f45de69d3410a5e8a 100644 (file)
@@ -24,7 +24,7 @@ from Configuration import Configuration
 from Check import Check\r
 import Common.GlobalData as GlobalData\r
 \r
 from Check import Check\r
 import Common.GlobalData as GlobalData\r
 \r
-from Common.String import NormPath\r
+from Common.StringUtils import NormPath\r
 from Common.BuildVersion import gBUILD_VERSION\r
 from Common import BuildToolError\r
 from Common.Misc import PathClass\r
 from Common.BuildVersion import gBUILD_VERSION\r
 from Common import BuildToolError\r
 from Common.Misc import PathClass\r
index 4d61cd1cea917db996e81f8f65890337ed4d2965..3749f6a2699e415ffed2063b826d2d9e0048e9e8 100644 (file)
@@ -26,7 +26,7 @@ import EccToolError
 \r
 from CommonDataClass.DataClass import *\r
 from Common.DataType import *\r
 \r
 from CommonDataClass.DataClass import *\r
 from Common.DataType import *\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData\r
 from Common.Expression import *\r
 from CommonDataClass.Exceptions import *\r
 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData\r
 from Common.Expression import *\r
 from CommonDataClass.Exceptions import *\r
index 786868d55d99334e8f27faf691def009e7e7c2b8..dfd1146af749c89605482d6f0db42c490978db68 100644 (file)
@@ -18,7 +18,7 @@ import Common.LongFilePathOs as os, time, glob
 import Common.EdkLogger as EdkLogger\r
 import EotGlobalData\r
 from optparse import OptionParser\r
 import Common.EdkLogger as EdkLogger\r
 import EotGlobalData\r
 from optparse import OptionParser\r
-from Common.String import NormPath\r
+from Common.StringUtils import NormPath\r
 from Common import BuildToolError\r
 from Common.Misc import GuidStructureStringToGuidString, sdict\r
 from InfParserLite import *\r
 from Common import BuildToolError\r
 from Common.Misc import GuidStructureStringToGuidString, sdict\r
 from InfParserLite import *\r
index 8867bb5dc23a7ea97a7b29431e33a7dfe2cc3c2a..584a95d6f3e43d1ff4ad52f86edd5ca3ee97c54c 100644 (file)
@@ -19,7 +19,7 @@ import Common.EdkLogger as EdkLogger
 from Common.DataType import *\r
 from CommonDataClass.DataClass import *\r
 from Common.Identification import *\r
 from Common.DataType import *\r
 from CommonDataClass.DataClass import *\r
 from Common.Identification import *\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Parser import *\r
 import Database\r
 \r
 from Parser import *\r
 import Database\r
 \r
index 14c287588a017b37e16ca4ec9f09b756947ea943..ff88e957ad0df6f99eb2045e17bafa96272ae0b1 100644 (file)
@@ -19,9 +19,9 @@ import Common.LongFilePathOs as os, re
 import Common.EdkLogger as EdkLogger\r
 from Common.DataType import *\r
 from CommonDataClass.DataClass import *\r
 import Common.EdkLogger as EdkLogger\r
 from Common.DataType import *\r
 from CommonDataClass.DataClass import *\r
-from Common.String import CleanString, GetSplitValueList, ReplaceMacro\r
+from Common.StringUtils import CleanString, GetSplitValueList, ReplaceMacro\r
 import EotGlobalData\r
 import EotGlobalData\r
-from Common.String import GetSplitList\r
+from Common.StringUtils import GetSplitList\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 \r
 ## PreProcess() method\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 \r
 ## PreProcess() method\r
index 7cf792b5b251ec28f7432ddac12a6439782c5ec1..6b81b42620d73cfe6782e52830e2bce16bd411b7 100644 (file)
@@ -21,7 +21,7 @@ import StringIO
 import FfsFileStatement\r
 from GenFdsGlobalVariable import GenFdsGlobalVariable\r
 from CommonDataClass.FdfClass import AprioriSectionClassObject\r
 import FfsFileStatement\r
 from GenFdsGlobalVariable import GenFdsGlobalVariable\r
 from CommonDataClass.FdfClass import AprioriSectionClassObject\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.Misc import SaveFileOnChange,PathClass\r
 from Common import EdkLogger\r
 from Common.BuildToolError import *\r
 from Common.Misc import SaveFileOnChange,PathClass\r
 from Common import EdkLogger\r
 from Common.BuildToolError import *\r
index 4518d8f2af7c5ae09350d82d04659b4486455225..ddc5c930d4eaa64ade3edad86d1ea74d01e8be36 100644 (file)
@@ -48,12 +48,12 @@ from GenFdsGlobalVariable import GenFdsGlobalVariable
 from Common.BuildToolError import *\r
 from Common import EdkLogger\r
 from Common.Misc import PathClass\r
 from Common.BuildToolError import *\r
 from Common import EdkLogger\r
 from Common.Misc import PathClass\r
-from Common.String import NormPath\r
+from Common.StringUtils import NormPath\r
 import Common.GlobalData as GlobalData\r
 from Common.Expression import *\r
 from Common import GlobalData\r
 from Common.DataType import *\r
 import Common.GlobalData as GlobalData\r
 from Common.Expression import *\r
 from Common import GlobalData\r
 from Common.DataType import *\r
-from Common.String import ReplaceMacro\r
+from Common.StringUtils import ReplaceMacro\r
 import uuid\r
 from Common.Misc import tdict\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 import uuid\r
 from Common.Misc import tdict\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
index c332eee6079dbfb294c87bb199ff5acb43c77d17..b26821b29052ae7b3fcf8d262541de23c40ff38d 100644 (file)
@@ -29,7 +29,7 @@ import RuleSimpleFile
 import RuleComplexFile\r
 from CommonDataClass.FdfClass import FfsInfStatementClassObject\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 import RuleComplexFile\r
 from CommonDataClass.FdfClass import FfsInfStatementClassObject\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.Misc import PathClass\r
 from Common.Misc import GuidStructureByteArrayToGuidString\r
 from Common.Misc import ProcessDuplicatedInf\r
 from Common.Misc import PathClass\r
 from Common.Misc import GuidStructureByteArrayToGuidString\r
 from Common.Misc import ProcessDuplicatedInf\r
index f0b51e25dfa2f29788f78407aeabce98fa711cd9..339b9986736907b52fa9c7b297f6da2642c01bb2 100644 (file)
@@ -32,7 +32,7 @@ import Common.ToolDefClassObject as ToolDefClassObject
 from Common.DataType import *\r
 import Common.GlobalData as GlobalData\r
 from Common import EdkLogger\r
 from Common.DataType import *\r
 import Common.GlobalData as GlobalData\r
 from Common import EdkLogger\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.Misc import DirCache, PathClass\r
 from Common.Misc import SaveFileOnChange\r
 from Common.Misc import ClearDuplicatedInf\r
 from Common.Misc import DirCache, PathClass\r
 from Common.Misc import SaveFileOnChange\r
 from Common.Misc import ClearDuplicatedInf\r
index a865ac4436d5c39d031e3ea3e90b6da11cafd459..79891b3b82a4738c76b1bde910155e48e7350d6b 100644 (file)
@@ -22,7 +22,7 @@ import OptionRom
 import Common.GlobalData as GlobalData\r
 \r
 from Common.DataType import *\r
 import Common.GlobalData as GlobalData\r
 \r
 from Common.DataType import *\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from FfsInfStatement import FfsInfStatement\r
 from GenFdsGlobalVariable import GenFdsGlobalVariable\r
 \r
 from FfsInfStatement import FfsInfStatement\r
 from GenFdsGlobalVariable import GenFdsGlobalVariable\r
 \r
index 8466f6ebab33734ffa4fb1da29ab8306f403af37..d78b12d5050d166489b1957987de529825c3741b 100644 (file)
@@ -46,7 +46,7 @@ COMMON_PYTHON=$(BASE_TOOLS_PATH)\Source\Python\Common\BuildToolError.py \
               $(BASE_TOOLS_PATH)\Source\Python\Common\LongFilePathSupport.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\Misc.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\Parsing.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\LongFilePathSupport.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\Misc.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\Parsing.py \\r
-              $(BASE_TOOLS_PATH)\Source\Python\Common\String.py \\r
+              $(BASE_TOOLS_PATH)\Source\Python\Common\StringUtils.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\TargetTxtClassObject.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\ToolDefClassObject.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\VpdInfoFile.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\TargetTxtClassObject.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\ToolDefClassObject.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\VpdInfoFile.py \\r
@@ -167,7 +167,7 @@ CMD_UPT=$(BASE_TOOLS_PATH)\Source\Python\UPT\Core\DependencyRules.py \
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\Misc.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\ParserValidate.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\Parsing.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\Misc.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\ParserValidate.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\Parsing.py \\r
-    $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\String.py \\r
+    $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\StringUtils.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\UniClassObject.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\Xml\XmlRoutines.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Logger\Log.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\UniClassObject.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Library\Xml\XmlRoutines.py \\r
     $(BASE_TOOLS_PATH)\Source\Python\UPT\Logger\Log.py \\r
index 9c3d7bd9345f768ffe53516d7ba0fc4f1637222f..2c37592fc67cdd504d7c0ca1d34e42b4d63bbec2 100644 (file)
@@ -17,7 +17,7 @@
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 \r
 ## TableDataModel\r
 #\r
 \r
 ## TableDataModel\r
 #\r
index 6b7d22c9384c09724d612bc7c981f21ede94a713..97139c58d893215506174b6d73375e6840cbd6e7 100644 (file)
@@ -17,7 +17,7 @@
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 \r
 ## TableDec\r
 #\r
 \r
 ## TableDec\r
 #\r
index 69477d544d8e3e6d5f2f9c8950ee22b7d10bb6ed..4ac54933aa3b93285fefc61f14585b4c38693501 100644 (file)
@@ -17,7 +17,7 @@
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 \r
 ## TableDsc\r
 #\r
 \r
 ## TableDsc\r
 #\r
index 740105c8f99d721fc68923e71b303757a5869e00..bccf25ca45d5ff7155c9098699de6eea97099dc1 100644 (file)
@@ -17,7 +17,7 @@
 import Common.EdkLogger as EdkLogger\r
 import Common.LongFilePathOs as os, time\r
 from Table import Table\r
 import Common.EdkLogger as EdkLogger\r
 import Common.LongFilePathOs as os, time\r
 from Table import Table\r
-from Common.String import ConvertToSqlString2\r
+from Common.StringUtils import ConvertToSqlString2\r
 import Eot.EotToolError as EotToolError\r
 import Eot.EotGlobalData as EotGlobalData\r
 \r
 import Eot.EotToolError as EotToolError\r
 import Eot.EotGlobalData as EotGlobalData\r
 \r
index 927b5d1a3be637833ebe55bfb5e4cb237c91697a..eea8e9404d55c605dc1a9bf8ad14ceb395792c99 100644 (file)
@@ -17,7 +17,7 @@
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 \r
 ## TableFdf\r
 #\r
 \r
 ## TableFdf\r
 #\r
index caf749e9d3c5348422771dd37b19914cf0dffc9c..ac762ea7fcc01c7f98e05a0a44a9863561c9f534 100644 (file)
@@ -16,7 +16,7 @@
 #\r
 import Common.EdkLogger as EdkLogger\r
 from Table import Table\r
 #\r
 import Common.EdkLogger as EdkLogger\r
 from Table import Table\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 import Common.LongFilePathOs as os\r
 from CommonDataClass.DataClass import FileClass\r
 \r
 import Common.LongFilePathOs as os\r
 from CommonDataClass.DataClass import FileClass\r
 \r
index 3d7c2d0ea5a0c6b8fc1130234f5cd6f5bc2a4794..3d40bd61f6953d17aae220ca7c36f8ea5ef243ab 100644 (file)
@@ -16,7 +16,7 @@
 #\r
 import Common.EdkLogger as EdkLogger\r
 from Table import Table\r
 #\r
 import Common.EdkLogger as EdkLogger\r
 from Table import Table\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 \r
 ## TableFunction\r
 #\r
 \r
 ## TableFunction\r
 #\r
index bcd6d6e1c1526832eeb14a4cd497b75449d0899b..0ec8b3c162ceaff2cd0bfe928756d69ef7067859 100644 (file)
@@ -15,7 +15,7 @@
 # Import Modules\r
 #\r
 import Common.EdkLogger as EdkLogger\r
 # Import Modules\r
 #\r
 import Common.EdkLogger as EdkLogger\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 from Table import Table\r
 \r
 ## TableIdentifier\r
 from Table import Table\r
 \r
 ## TableIdentifier\r
index b6e300b150c1076c91ac76137c2e4c8abc52cd88..478b77776e359e535b60f3cbe9acfb8c1a768b2d 100644 (file)
@@ -17,7 +17,7 @@
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
 import Common.EdkLogger as EdkLogger\r
 import CommonDataClass.DataClass as DataClass\r
 from Table import Table\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 \r
 ## TableInf\r
 #\r
 \r
 ## TableInf\r
 #\r
index 19623f98f42c465f6c11cf9abdb76cf7e5f9e69e..ca1c0f0c8ab21733d3a15eb60a100aad4de60c76 100644 (file)
@@ -16,7 +16,7 @@
 #\r
 import Common.EdkLogger as EdkLogger\r
 from Table import Table\r
 #\r
 import Common.EdkLogger as EdkLogger\r
 from Table import Table\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 \r
 ## TablePcd\r
 #\r
 \r
 ## TablePcd\r
 #\r
index e1d2537394b2076ffe80b346fd1da5b338c482e4..f377b10561dc00f552260eadf1a102dcaeab0981 100644 (file)
@@ -15,7 +15,7 @@
 # Import Modules\r
 #\r
 import Common.EdkLogger as EdkLogger\r
 # Import Modules\r
 #\r
 import Common.EdkLogger as EdkLogger\r
-from Common.String import ConvertToSqlString\r
+from Common.StringUtils import ConvertToSqlString\r
 from Table import Table\r
 \r
 ## TableQuery\r
 from Table import Table\r
 \r
 ## TableQuery\r
index 4af0e98d86b4e01c8a7a313ecd261010f93cf5ec..9ce1d0aa25182a1e4920da8da7d3894ab402d42b 100644 (file)
@@ -17,7 +17,7 @@
 import Common.EdkLogger as EdkLogger\r
 import Common.LongFilePathOs as os, time\r
 from Table import Table\r
 import Common.EdkLogger as EdkLogger\r
 import Common.LongFilePathOs as os, time\r
 from Table import Table\r
-from Common.String import ConvertToSqlString2\r
+from Common.StringUtils import ConvertToSqlString2\r
 import EccToolError as EccToolError\r
 import EccGlobalData as EccGlobalData\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 import EccToolError as EccToolError\r
 import EccGlobalData as EccGlobalData\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
diff --git a/BaseTools/Source/Python/UPT/Library/String.py b/BaseTools/Source/Python/UPT/Library/String.py
deleted file mode 100644 (file)
index b79891e..0000000
+++ /dev/null
@@ -1,990 +0,0 @@
-## @file\r
-# This file is used to define common string related functions used in parsing\r
-# process\r
-#\r
-# Copyright (c) 2011 - 2016, 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
-String\r
-'''\r
-##\r
-# Import Modules\r
-#\r
-import re\r
-import os.path\r
-from string import strip\r
-import Logger.Log as Logger\r
-import Library.DataType as DataType\r
-from Logger.ToolError import FORMAT_INVALID\r
-from Logger.ToolError import PARSER_ERROR\r
-from Logger import StringTable as ST\r
-\r
-#\r
-# Regular expression for matching macro used in DSC/DEC/INF file inclusion\r
-#\r
-gMACRO_PATTERN = re.compile("\$\(([_A-Z][_A-Z0-9]*)\)", re.UNICODE)\r
-\r
-## GetSplitValueList\r
-#\r
-# Get a value list from a string with multiple values splited with SplitTag\r
-# The default SplitTag is DataType.TAB_VALUE_SPLIT\r
-# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']\r
-#\r
-# @param String:    The input string to be splitted\r
-# @param SplitTag:  The split key, default is DataType.TAB_VALUE_SPLIT\r
-# @param MaxSplit:  The max number of split values, default is -1\r
-#\r
-#\r
-def GetSplitValueList(String, SplitTag=DataType.TAB_VALUE_SPLIT, MaxSplit= -1):\r
-    return map(lambda l: l.strip(), String.split(SplitTag, MaxSplit))\r
-\r
-## MergeArches\r
-#\r
-# Find a key's all arches in dict, add the new arch to the list\r
-# If not exist any arch, set the arch directly\r
-#\r
-# @param Dict:  The input value for Dict\r
-# @param Key:   The input value for Key\r
-# @param Arch:  The Arch to be added or merged\r
-#\r
-def MergeArches(Dict, Key, Arch):\r
-    if Key in Dict.keys():\r
-        Dict[Key].append(Arch)\r
-    else:\r
-        Dict[Key] = Arch.split()\r
-\r
-## GenDefines\r
-#\r
-# Parse a string with format "DEFINE <VarName> = <PATH>"\r
-# Generate a map Defines[VarName] = PATH\r
-# Return False if invalid format\r
-#\r
-# @param String:   String with DEFINE statement\r
-# @param Arch:     Supportted Arch\r
-# @param Defines:  DEFINE statement to be parsed\r
-#\r
-def GenDefines(String, Arch, Defines):\r
-    if String.find(DataType.TAB_DEFINE + ' ') > -1:\r
-        List = String.replace(DataType.TAB_DEFINE + ' ', '').\\r
-        split(DataType.TAB_EQUAL_SPLIT)\r
-        if len(List) == 2:\r
-            Defines[(CleanString(List[0]), Arch)] = CleanString(List[1])\r
-            return 0\r
-        else:\r
-            return -1\r
-    return 1\r
-\r
-## GetLibraryClassesWithModuleType\r
-#\r
-# Get Library Class definition when no module type defined\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
-def GetLibraryClassesWithModuleType(Lines, Key, KeyValues, CommentCharacter):\r
-    NewKey = SplitModuleType(Key)\r
-    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
-    LineList = Lines.splitlines()\r
-    for Line in LineList:\r
-        Line = CleanString(Line, CommentCharacter)\r
-        if Line != '' and Line[0] != CommentCharacter:\r
-            KeyValues.append([CleanString(Line, CommentCharacter), NewKey[1]])\r
-\r
-    return True\r
-\r
-## GetDynamics\r
-#\r
-# Get Dynamic Pcds\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
-def GetDynamics(Lines, Key, KeyValues, CommentCharacter):\r
-    #\r
-    # Get SkuId Name List\r
-    #\r
-    SkuIdNameList = SplitModuleType(Key)\r
-\r
-    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
-    LineList = Lines.splitlines()\r
-    for Line in LineList:\r
-        Line = CleanString(Line, CommentCharacter)\r
-        if Line != '' and Line[0] != CommentCharacter:\r
-            KeyValues.append([CleanString(Line, CommentCharacter), SkuIdNameList[1]])\r
-\r
-    return True\r
-\r
-## SplitModuleType\r
-#\r
-# Split ModuleType out of section defien to get key\r
-# [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [\r
-# 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]\r
-#\r
-# @param Key:  String to be parsed\r
-#\r
-def SplitModuleType(Key):\r
-    KeyList = Key.split(DataType.TAB_SPLIT)\r
-    #\r
-    # Fill in for arch\r
-    #\r
-    KeyList.append('')\r
-    #\r
-    # Fill in for moduletype\r
-    #\r
-    KeyList.append('')\r
-    ReturnValue = []\r
-    KeyValue = KeyList[0]\r
-    if KeyList[1] != '':\r
-        KeyValue = KeyValue + DataType.TAB_SPLIT + KeyList[1]\r
-    ReturnValue.append(KeyValue)\r
-    ReturnValue.append(GetSplitValueList(KeyList[2]))\r
-\r
-    return ReturnValue\r
-\r
-## Replace macro in string\r
-#\r
-# This method replace macros used in given string. The macros are given in a\r
-# dictionary.\r
-#\r
-# @param String             String to be processed\r
-# @param MacroDefinitions   The macro definitions in the form of dictionary\r
-# @param SelfReplacement    To decide whether replace un-defined macro to ''\r
-# @param Line:              The content contain line string and line number\r
-# @param FileName:        The meta-file file name\r
-#\r
-def ReplaceMacro(String, MacroDefinitions=None, SelfReplacement=False, Line=None, FileName=None, Flag=False):\r
-    LastString = String\r
-    if MacroDefinitions is None:\r
-        MacroDefinitions = {}\r
-    while MacroDefinitions:\r
-        QuotedStringList = []\r
-        HaveQuotedMacroFlag = False\r
-        if not Flag:\r
-            MacroUsed = gMACRO_PATTERN.findall(String)\r
-        else:\r
-            ReQuotedString = re.compile('\"')\r
-            QuotedStringList = ReQuotedString.split(String)\r
-            if len(QuotedStringList) >= 3:\r
-                HaveQuotedMacroFlag = True\r
-            Count = 0\r
-            MacroString = ""\r
-            for QuotedStringItem in QuotedStringList:\r
-                Count += 1\r
-                if Count % 2 != 0:\r
-                    MacroString += QuotedStringItem\r
-\r
-                if Count == len(QuotedStringList) and Count % 2 == 0:\r
-                    MacroString += QuotedStringItem\r
-\r
-            MacroUsed = gMACRO_PATTERN.findall(MacroString)\r
-        #\r
-        # no macro found in String, stop replacing\r
-        #\r
-        if len(MacroUsed) == 0:\r
-            break\r
-        for Macro in MacroUsed:\r
-            if Macro not in MacroDefinitions:\r
-                if SelfReplacement:\r
-                    String = String.replace("$(%s)" % Macro, '')\r
-                    Logger.Debug(5, "Delete undefined MACROs in file %s line %d: %s!" % (FileName, Line[1], Line[0]))\r
-                continue\r
-            if not HaveQuotedMacroFlag:\r
-                String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro])\r
-            else:\r
-                Count = 0\r
-                for QuotedStringItem in QuotedStringList:\r
-                    Count += 1\r
-                    if Count % 2 != 0:\r
-                        QuotedStringList[Count - 1] = QuotedStringList[Count - 1].replace("$(%s)" % Macro,\r
-                                                                        MacroDefinitions[Macro])\r
-                    elif Count == len(QuotedStringList) and Count % 2 == 0:\r
-                        QuotedStringList[Count - 1] = QuotedStringList[Count - 1].replace("$(%s)" % Macro,\r
-                                                                        MacroDefinitions[Macro])\r
-\r
-        RetString = ''\r
-        if HaveQuotedMacroFlag:\r
-            Count = 0\r
-            for QuotedStringItem in QuotedStringList:\r
-                Count += 1\r
-                if Count != len(QuotedStringList):\r
-                    RetString += QuotedStringList[Count - 1] + "\""\r
-                else:\r
-                    RetString += QuotedStringList[Count - 1]\r
-\r
-            String = RetString\r
-\r
-        #\r
-        # in case there's macro not defined\r
-        #\r
-        if String == LastString:\r
-            break\r
-        LastString = String\r
-\r
-    return String\r
-\r
-## NormPath\r
-#\r
-# Create a normal path\r
-# And replace DFEINE in the path\r
-#\r
-# @param Path:     The input value for Path to be converted\r
-# @param Defines:  A set for DEFINE statement\r
-#\r
-def NormPath(Path, Defines=None):\r
-    IsRelativePath = False\r
-    if Defines is None:\r
-        Defines = {}\r
-    if Path:\r
-        if Path[0] == '.':\r
-            IsRelativePath = True\r
-        #\r
-        # Replace with Define\r
-        #\r
-        if Defines:\r
-            Path = ReplaceMacro(Path, Defines)\r
-        #\r
-        # To local path format\r
-        #\r
-        Path = os.path.normpath(Path)\r
-\r
-    if IsRelativePath and Path[0] != '.':\r
-        Path = os.path.join('.', Path)\r
-    return Path\r
-\r
-## CleanString\r
-#\r
-# Remove comments in a string\r
-# Remove spaces\r
-#\r
-# @param Line:              The string to be cleaned\r
-# @param CommentCharacter:  Comment char, used to ignore comment content,\r
-#                           default is DataType.TAB_COMMENT_SPLIT\r
-#\r
-def CleanString(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):\r
-    #\r
-    # remove whitespace\r
-    #\r
-    Line = Line.strip()\r
-    #\r
-    # Replace EDK1's comment character\r
-    #\r
-    if AllowCppStyleComment:\r
-        Line = Line.replace(DataType.TAB_COMMENT_EDK1_SPLIT, CommentCharacter)\r
-    #\r
-    # remove comments, but we should escape comment character in string\r
-    #\r
-    InString = False\r
-    for Index in range(0, len(Line)):\r
-        if Line[Index] == '"':\r
-            InString = not InString\r
-        elif Line[Index] == CommentCharacter and not InString:\r
-            Line = Line[0: Index]\r
-            break\r
-    #\r
-    # remove whitespace again\r
-    #\r
-    Line = Line.strip()\r
-\r
-    return Line\r
-\r
-## CleanString2\r
-#\r
-# Split comments in a string\r
-# Remove spaces\r
-#\r
-# @param Line:              The string to be cleaned\r
-# @param CommentCharacter:  Comment char, used to ignore comment content,\r
-#                           default is DataType.TAB_COMMENT_SPLIT\r
-#\r
-def CleanString2(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):\r
-    #\r
-    # remove whitespace\r
-    #\r
-    Line = Line.strip()\r
-    #\r
-    # Replace EDK1's comment character\r
-    #\r
-    if AllowCppStyleComment:\r
-        Line = Line.replace(DataType.TAB_COMMENT_EDK1_SPLIT, CommentCharacter)\r
-    #\r
-    # separate comments and statements\r
-    #\r
-    LineParts = Line.split(CommentCharacter, 1)\r
-    #\r
-    # remove whitespace again\r
-    #\r
-    Line = LineParts[0].strip()\r
-    if len(LineParts) > 1:\r
-        Comment = LineParts[1].strip()\r
-        #\r
-        # Remove prefixed and trailing comment characters\r
-        #\r
-        Start = 0\r
-        End = len(Comment)\r
-        while Start < End and Comment.startswith(CommentCharacter, Start, End):\r
-            Start += 1\r
-        while End >= 0 and Comment.endswith(CommentCharacter, Start, End):\r
-            End -= 1\r
-        Comment = Comment[Start:End]\r
-        Comment = Comment.strip()\r
-    else:\r
-        Comment = ''\r
-\r
-    return Line, Comment\r
-\r
-## GetMultipleValuesOfKeyFromLines\r
-#\r
-# Parse multiple strings to clean comment and spaces\r
-# The result is saved to KeyValues\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
-def GetMultipleValuesOfKeyFromLines(Lines, Key, KeyValues, CommentCharacter):\r
-    if Key:\r
-        pass\r
-    if KeyValues:\r
-        pass\r
-    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
-    LineList = Lines.split('\n')\r
-    for Line in LineList:\r
-        Line = CleanString(Line, CommentCharacter)\r
-        if Line != '' and Line[0] != CommentCharacter:\r
-            KeyValues += [Line]\r
-    return True\r
-\r
-## GetDefineValue\r
-#\r
-# Parse a DEFINE statement to get defined value\r
-# DEFINE Key Value\r
-#\r
-# @param String:            The content to be parsed\r
-# @param Key:               The key of DEFINE statement\r
-# @param CommentCharacter:  Comment char, used to ignore comment content\r
-#\r
-def GetDefineValue(String, Key, CommentCharacter):\r
-    if CommentCharacter:\r
-        pass\r
-    String = CleanString(String)\r
-    return String[String.find(Key + ' ') + len(Key + ' ') : ]\r
-\r
-## GetSingleValueOfKeyFromLines\r
-#\r
-# Parse multiple strings as below to get value of each definition line\r
-# Key1 = Value1\r
-# Key2 = Value2\r
-# The result is saved to Dictionary\r
-#\r
-# @param Lines:                The content to be parsed\r
-# @param Dictionary:           To store data after parsing\r
-# @param CommentCharacter:     Comment char, be used to ignore comment content\r
-# @param KeySplitCharacter:    Key split char, between key name and key value.\r
-#                              Key1 = Value1, '=' is the key split char\r
-# @param ValueSplitFlag:       Value split flag, be used to decide if has\r
-#                              multiple values\r
-# @param ValueSplitCharacter:  Value split char, be used to split multiple\r
-#                              values. Key1 = Value1|Value2, '|' is the value\r
-#                              split char\r
-#\r
-def GetSingleValueOfKeyFromLines(Lines, Dictionary, CommentCharacter, KeySplitCharacter, \\r
-                                 ValueSplitFlag, ValueSplitCharacter):\r
-    Lines = Lines.split('\n')\r
-    Keys = []\r
-    Value = ''\r
-    DefineValues = ['']\r
-    SpecValues = ['']\r
-\r
-    for Line in Lines:\r
-        #\r
-        # Handle DEFINE and SPEC\r
-        #\r
-        if Line.find(DataType.TAB_INF_DEFINES_DEFINE + ' ') > -1:\r
-            if '' in DefineValues:\r
-                DefineValues.remove('')\r
-            DefineValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_DEFINE, CommentCharacter))\r
-            continue\r
-        if Line.find(DataType.TAB_INF_DEFINES_SPEC + ' ') > -1:\r
-            if '' in SpecValues:\r
-                SpecValues.remove('')\r
-            SpecValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_SPEC, CommentCharacter))\r
-            continue\r
-\r
-        #\r
-        # Handle Others\r
-        #\r
-        LineList = Line.split(KeySplitCharacter, 1)\r
-        if len(LineList) >= 2:\r
-            Key = LineList[0].split()\r
-            if len(Key) == 1 and Key[0][0] != CommentCharacter:\r
-                #\r
-                # Remove comments and white spaces\r
-                #\r
-                LineList[1] = CleanString(LineList[1], CommentCharacter)\r
-                if ValueSplitFlag:\r
-                    Value = map(strip, LineList[1].split(ValueSplitCharacter))\r
-                else:\r
-                    Value = CleanString(LineList[1], CommentCharacter).splitlines()\r
-\r
-                if Key[0] in Dictionary:\r
-                    if Key[0] not in Keys:\r
-                        Dictionary[Key[0]] = Value\r
-                        Keys.append(Key[0])\r
-                    else:\r
-                        Dictionary[Key[0]].extend(Value)\r
-                else:\r
-                    Dictionary[DataType.TAB_INF_DEFINES_MACRO][Key[0]] = Value[0]\r
-\r
-    if DefineValues == []:\r
-        DefineValues = ['']\r
-    if SpecValues == []:\r
-        SpecValues = ['']\r
-    Dictionary[DataType.TAB_INF_DEFINES_DEFINE] = DefineValues\r
-    Dictionary[DataType.TAB_INF_DEFINES_SPEC] = SpecValues\r
-\r
-    return True\r
-\r
-## The content to be parsed\r
-#\r
-# Do pre-check for a file before it is parsed\r
-# Check $()\r
-# Check []\r
-#\r
-# @param FileName:       Used for error report\r
-# @param FileContent:    File content to be parsed\r
-# @param SupSectionTag:  Used for error report\r
-#\r
-def PreCheck(FileName, FileContent, SupSectionTag):\r
-    if SupSectionTag:\r
-        pass\r
-    LineNo = 0\r
-    IsFailed = False\r
-    NewFileContent = ''\r
-    for Line in FileContent.splitlines():\r
-        LineNo = LineNo + 1\r
-        #\r
-        # Clean current line\r
-        #\r
-        Line = CleanString(Line)\r
-        #\r
-        # Remove commented line\r
-        #\r
-        if Line.find(DataType.TAB_COMMA_SPLIT) == 0:\r
-            Line = ''\r
-        #\r
-        # Check $()\r
-        #\r
-        if Line.find('$') > -1:\r
-            if Line.find('$(') < 0 or Line.find(')') < 0:\r
-                Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)\r
-        #\r
-        # Check []\r
-        #\r
-        if Line.find('[') > -1 or Line.find(']') > -1:\r
-            #\r
-            # Only get one '[' or one ']'\r
-            #\r
-            if not (Line.find('[') > -1 and Line.find(']') > -1):\r
-                Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)\r
-        #\r
-        # Regenerate FileContent\r
-        #\r
-        NewFileContent = NewFileContent + Line + '\r\n'\r
-\r
-    if IsFailed:\r
-        Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)\r
-\r
-    return NewFileContent\r
-\r
-## CheckFileType\r
-#\r
-# Check if the Filename is including ExtName\r
-# Return True if it exists\r
-# Raise a error message if it not exists\r
-#\r
-# @param CheckFilename:      Name of the file to be checked\r
-# @param ExtName:            Ext name of the file to be checked\r
-# @param ContainerFilename:  The container file which describes the file to be\r
-#                            checked, used for error report\r
-# @param SectionName:        Used for error report\r
-# @param Line:               The line in container file which defines the file\r
-#                            to be checked\r
-#\r
-def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo= -1):\r
-    if CheckFilename != '' and CheckFilename is not None:\r
-        (Root, Ext) = os.path.splitext(CheckFilename)\r
-        if Ext.upper() != ExtName.upper() and Root:\r
-            ContainerFile = open(ContainerFilename, 'r').read()\r
-            if LineNo == -1:\r
-                LineNo = GetLineNo(ContainerFile, Line)\r
-            ErrorMsg = ST.ERR_SECTIONNAME_INVALID % (SectionName, CheckFilename, ExtName)\r
-            Logger.Error("Parser", PARSER_ERROR, ErrorMsg, Line=LineNo, \\r
-                         File=ContainerFilename, RaiseError=Logger.IS_RAISE_ERROR)\r
-\r
-    return True\r
-\r
-## CheckFileExist\r
-#\r
-# Check if the file exists\r
-# Return True if it exists\r
-# Raise a error message if it not exists\r
-#\r
-# @param CheckFilename:      Name of the file to be checked\r
-# @param WorkspaceDir:       Current workspace dir\r
-# @param ContainerFilename:  The container file which describes the file to\r
-#                            be checked, used for error report\r
-# @param SectionName:        Used for error report\r
-# @param Line:               The line in container file which defines the\r
-#                            file to be checked\r
-#\r
-def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo= -1):\r
-    CheckFile = ''\r
-    if CheckFilename != '' and CheckFilename is not None:\r
-        CheckFile = WorkspaceFile(WorkspaceDir, CheckFilename)\r
-        if not os.path.isfile(CheckFile):\r
-            ContainerFile = open(ContainerFilename, 'r').read()\r
-            if LineNo == -1:\r
-                LineNo = GetLineNo(ContainerFile, Line)\r
-            ErrorMsg = ST.ERR_CHECKFILE_NOTFOUND % (CheckFile, SectionName)\r
-            Logger.Error("Parser", PARSER_ERROR, ErrorMsg,\r
-                            File=ContainerFilename, Line=LineNo, RaiseError=Logger.IS_RAISE_ERROR)\r
-    return CheckFile\r
-\r
-## GetLineNo\r
-#\r
-# Find the index of a line in a file\r
-#\r
-# @param FileContent:  Search scope\r
-# @param Line:         Search key\r
-#\r
-def GetLineNo(FileContent, Line, IsIgnoreComment=True):\r
-    LineList = FileContent.splitlines()\r
-    for Index in range(len(LineList)):\r
-        if LineList[Index].find(Line) > -1:\r
-            #\r
-            # Ignore statement in comment\r
-            #\r
-            if IsIgnoreComment:\r
-                if LineList[Index].strip()[0] == DataType.TAB_COMMENT_SPLIT:\r
-                    continue\r
-            return Index + 1\r
-\r
-    return -1\r
-\r
-## RaiseParserError\r
-#\r
-# Raise a parser error\r
-#\r
-# @param Line:     String which has error\r
-# @param Section:  Used for error report\r
-# @param File:     File which has the string\r
-# @param Format:   Correct format\r
-#\r
-def RaiseParserError(Line, Section, File, Format='', LineNo= -1):\r
-    if LineNo == -1:\r
-        LineNo = GetLineNo(open(os.path.normpath(File), 'r').read(), Line)\r
-    ErrorMsg = ST.ERR_INVALID_NOTFOUND % (Line, Section)\r
-    if Format != '':\r
-        Format = "Correct format is " + Format\r
-    Logger.Error("Parser", PARSER_ERROR, ErrorMsg, File=File, Line=LineNo, \\r
-                 ExtraData=Format, RaiseError=Logger.IS_RAISE_ERROR)\r
-\r
-## WorkspaceFile\r
-#\r
-# Return a full path with workspace dir\r
-#\r
-# @param WorkspaceDir:  Workspace dir\r
-# @param Filename:      Relative file name\r
-#\r
-def WorkspaceFile(WorkspaceDir, Filename):\r
-    return os.path.join(NormPath(WorkspaceDir), NormPath(Filename))\r
-\r
-## Split string\r
-#\r
-# Revmove '"' which startswith and endswith string\r
-#\r
-# @param String:  The string need to be splited\r
-#\r
-def SplitString(String):\r
-    if String.startswith('\"'):\r
-        String = String[1:]\r
-    if String.endswith('\"'):\r
-        String = String[:-1]\r
-    return String\r
-\r
-## Convert To Sql String\r
-#\r
-# Replace "'" with "''" in each item of StringList\r
-#\r
-# @param StringList:  A list for strings to be converted\r
-#\r
-def ConvertToSqlString(StringList):\r
-    return map(lambda s: s.replace("'", "''") , StringList)\r
-\r
-## Convert To Sql String\r
-#\r
-# Replace "'" with "''" in the String\r
-#\r
-# @param String:  A String to be converted\r
-#\r
-def ConvertToSqlString2(String):\r
-    return String.replace("'", "''")\r
-\r
-## GetStringOfList\r
-#\r
-# Get String of a List\r
-#\r
-# @param Lines: string list\r
-# @param Split: split character\r
-#\r
-def GetStringOfList(List, Split=' '):\r
-    if type(List) != type([]):\r
-        return List\r
-    Str = ''\r
-    for Item in List:\r
-        Str = Str + Item + Split\r
-    return Str.strip()\r
-\r
-## Get HelpTextList\r
-#\r
-# Get HelpTextList from HelpTextClassList\r
-#\r
-# @param HelpTextClassList: Help Text Class List\r
-#\r
-def GetHelpTextList(HelpTextClassList):\r
-    List = []\r
-    if HelpTextClassList:\r
-        for HelpText in HelpTextClassList:\r
-            if HelpText.String.endswith('\n'):\r
-                HelpText.String = HelpText.String[0: len(HelpText.String) - len('\n')]\r
-                List.extend(HelpText.String.split('\n'))\r
-    return List\r
-\r
-## Get String Array Length\r
-#\r
-# Get String Array Length\r
-#\r
-# @param String: the source string\r
-#\r
-def StringArrayLength(String):\r
-    if isinstance(String, unicode):\r
-        return (len(String) + 1) * 2 + 1\r
-    elif String.startswith('L"'):\r
-        return (len(String) - 3 + 1) * 2\r
-    elif String.startswith('"'):\r
-        return (len(String) - 2 + 1)\r
-    else:\r
-        return len(String.split()) + 1\r
-\r
-## RemoveDupOption\r
-#\r
-# Remove Dup Option\r
-#\r
-# @param OptionString: the option string\r
-# @param Which: Which flag\r
-# @param Against: Against flag\r
-#\r
-def RemoveDupOption(OptionString, Which="/I", Against=None):\r
-    OptionList = OptionString.split()\r
-    ValueList = []\r
-    if Against:\r
-        ValueList += Against\r
-    for Index in range(len(OptionList)):\r
-        Opt = OptionList[Index]\r
-        if not Opt.startswith(Which):\r
-            continue\r
-        if len(Opt) > len(Which):\r
-            Val = Opt[len(Which):]\r
-        else:\r
-            Val = ""\r
-        if Val in ValueList:\r
-            OptionList[Index] = ""\r
-        else:\r
-            ValueList.append(Val)\r
-    return " ".join(OptionList)\r
-\r
-## Check if the string is HexDgit\r
-#\r
-# Return true if all characters in the string are digits and there is at\r
-# least one character\r
-# or valid Hexs (started with 0x, following by hexdigit letters)\r
-# , false otherwise.\r
-# @param string: input string\r
-#\r
-def IsHexDigit(Str):\r
-    try:\r
-        int(Str, 10)\r
-        return True\r
-    except ValueError:\r
-        if len(Str) > 2 and Str.upper().startswith('0X'):\r
-            try:\r
-                int(Str, 16)\r
-                return True\r
-            except ValueError:\r
-                return False\r
-    return False\r
-\r
-## Check if the string is HexDgit and its interger value within limit of UINT32\r
-#\r
-# Return true if all characters in the string are digits and there is at\r
-# least one character\r
-# or valid Hexs (started with 0x, following by hexdigit letters)\r
-# , false otherwise.\r
-# @param string: input string\r
-#\r
-def IsHexDigitUINT32(Str):\r
-    try:\r
-        Value = int(Str, 10)\r
-        if (Value <= 0xFFFFFFFF) and (Value >= 0):\r
-            return True\r
-    except ValueError:\r
-        if len(Str) > 2 and Str.upper().startswith('0X'):\r
-            try:\r
-                Value = int(Str, 16)\r
-                if (Value <= 0xFFFFFFFF) and (Value >= 0):\r
-                    return True\r
-            except ValueError:\r
-                return False\r
-    return False\r
-\r
-## CleanSpecialChar\r
-#\r
-# The ASCII text files of type INF, DEC, INI are edited by developers,\r
-# and may contain characters that cannot be directly translated to strings that\r
-# are conformant with the UDP XML Schema.  Any characters in this category\r
-# (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF)\r
-# must be converted to a space character[0x20] as part of the parsing process.\r
-#\r
-def ConvertSpecialChar(Lines):\r
-    RetLines = []\r
-    for line in Lines:\r
-        ReMatchSpecialChar = re.compile(r"[\x00-\x08]|\x09|\x0b|\x0c|[\x0e-\x1f]|[\x7f-\xff]")\r
-        RetLines.append(ReMatchSpecialChar.sub(' ', line))\r
-\r
-    return RetLines\r
-\r
-## __GetTokenList\r
-#\r
-# Assume Str is a valid feature flag expression.\r
-# Return a list which contains tokens: alpha numeric token and other token\r
-# Whitespace are not stripped\r
-#\r
-def __GetTokenList(Str):\r
-    InQuote = False\r
-    Token = ''\r
-    TokenOP = ''\r
-    PreChar = ''\r
-    List = []\r
-    for Char in Str:\r
-        if InQuote:\r
-            Token += Char\r
-            if Char == '"' and PreChar != '\\':\r
-                InQuote = not InQuote\r
-                List.append(Token)\r
-                Token = ''\r
-            continue\r
-        if Char == '"':\r
-            if Token and Token != 'L':\r
-                List.append(Token)\r
-                Token = ''\r
-            if TokenOP:\r
-                List.append(TokenOP)\r
-                TokenOP = ''\r
-            InQuote = not InQuote\r
-            Token += Char\r
-            continue\r
-\r
-        if not (Char.isalnum() or Char in '_'):\r
-            TokenOP += Char\r
-            if Token:\r
-                List.append(Token)\r
-                Token = ''\r
-        else:\r
-            Token += Char\r
-            if TokenOP:\r
-                List.append(TokenOP)\r
-                TokenOP = ''\r
-\r
-        if PreChar == '\\' and Char == '\\':\r
-            PreChar = ''\r
-        else:\r
-            PreChar = Char\r
-    if Token:\r
-        List.append(Token)\r
-    if TokenOP:\r
-        List.append(TokenOP)\r
-    return List\r
-\r
-## ConvertNEToNOTEQ\r
-#\r
-# Convert NE operator to NOT EQ\r
-# For example: 1 NE 2 -> 1 NOT EQ 2\r
-#\r
-# @param Expr: Feature flag expression to be converted\r
-#\r
-def ConvertNEToNOTEQ(Expr):\r
-    List = __GetTokenList(Expr)\r
-    for Index in range(len(List)):\r
-        if List[Index] == 'NE':\r
-            List[Index] = 'NOT EQ'\r
-    return ''.join(List)\r
-\r
-## ConvertNOTEQToNE\r
-#\r
-# Convert NOT EQ operator to NE\r
-# For example: 1 NOT NE 2 -> 1 NE 2\r
-#\r
-# @param Expr: Feature flag expression to be converted\r
-#\r
-def ConvertNOTEQToNE(Expr):\r
-    List = __GetTokenList(Expr)\r
-    HasNOT = False\r
-    RetList = []\r
-    for Token in List:\r
-        if HasNOT and Token == 'EQ':\r
-            # At least, 'NOT' is in the list\r
-            while not RetList[-1].strip():\r
-                RetList.pop()\r
-            RetList[-1] = 'NE'\r
-            HasNOT = False\r
-            continue\r
-        if Token == 'NOT':\r
-            HasNOT = True\r
-        elif Token.strip():\r
-            HasNOT = False\r
-        RetList.append(Token)\r
-\r
-    return ''.join(RetList)\r
-\r
-## SplitPcdEntry\r
-#\r
-# Split an PCD entry string to Token.CName and PCD value and FFE.\r
-# NOTE: PCD Value and FFE can contain "|" in it's expression. And in INF specification, have below rule.\r
-# When using the characters "|" or "||" in an expression, the expression must be encapsulated in\r
-# open "(" and close ")" parenthesis.\r
-#\r
-# @param String    An PCD entry string need to be split.\r
-#\r
-# @return List     [PcdTokenCName, Value, FFE]\r
-#\r
-def SplitPcdEntry(String):\r
-    if not String:\r
-        return ['', '', ''], False\r
-\r
-    PcdTokenCName = ''\r
-    PcdValue = ''\r
-    PcdFeatureFlagExp = ''\r
-\r
-    ValueList = GetSplitValueList(String, "|", 1)\r
-\r
-    #\r
-    # Only contain TokenCName\r
-    #\r
-    if len(ValueList) == 1:\r
-        return [ValueList[0]], True\r
-\r
-    NewValueList = []\r
-\r
-    if len(ValueList) == 2:\r
-        PcdTokenCName = ValueList[0]\r
-\r
-        InQuote = False\r
-        InParenthesis = False\r
-        StrItem = ''\r
-        for StrCh in ValueList[1]:\r
-            if StrCh == '"':\r
-                InQuote = not InQuote\r
-            elif StrCh == '(' or StrCh == ')':\r
-                InParenthesis = not InParenthesis\r
-\r
-            if StrCh == '|':\r
-                if not InQuote or not InParenthesis:\r
-                    NewValueList.append(StrItem.strip())\r
-                    StrItem = ' '\r
-                    continue\r
-\r
-            StrItem += StrCh\r
-\r
-        NewValueList.append(StrItem.strip())\r
-\r
-        if len(NewValueList) == 1:\r
-            PcdValue = NewValueList[0]\r
-            return [PcdTokenCName, PcdValue], True\r
-        elif len(NewValueList) == 2:\r
-            PcdValue = NewValueList[0]\r
-            PcdFeatureFlagExp = NewValueList[1]\r
-            return [PcdTokenCName, PcdValue, PcdFeatureFlagExp], True\r
-        else:\r
-            return ['', '', ''], False\r
-\r
-    return ['', '', ''], False\r
-\r
-## Check if two arches matched?\r
-#\r
-# @param Arch1\r
-# @param Arch2\r
-#\r
-def IsMatchArch(Arch1, Arch2):\r
-    if 'COMMON' in Arch1 or 'COMMON' in Arch2:\r
-        return True\r
-    if isinstance(Arch1, basestring) and isinstance(Arch2, basestring):\r
-        if Arch1 == Arch2:\r
-            return True\r
-\r
-    if isinstance(Arch1, basestring) and isinstance(Arch2, list):\r
-        return Arch1 in Arch2\r
-\r
-    if isinstance(Arch2, basestring) and isinstance(Arch1, list):\r
-        return Arch2 in Arch1\r
-\r
-    if isinstance(Arch1, list) and isinstance(Arch2, list):\r
-        for Item1 in Arch1:\r
-            for Item2 in Arch2:\r
-                if Item1 == Item2:\r
-                    return True\r
-\r
-    return False\r
-\r
-# Search all files in FilePath to find the FileName with the largest index\r
-# Return the FileName with index +1 under the FilePath\r
-#\r
-def GetUniFileName(FilePath, FileName):\r
-    Files = []\r
-    try:\r
-        Files = os.listdir(FilePath)\r
-    except:\r
-        pass\r
-\r
-    LargestIndex = -1\r
-    IndexNotFound = True\r
-    for File in Files:\r
-        if File.upper().startswith(FileName.upper()) and File.upper().endswith('.UNI'):\r
-            Index = File.upper().replace(FileName.upper(), '').replace('.UNI', '')\r
-            if Index:\r
-                try:\r
-                    Index = int(Index)\r
-                except Exception:\r
-                    Index = -1\r
-            else:\r
-                IndexNotFound = False\r
-                Index = 0\r
-            if Index > LargestIndex:\r
-                LargestIndex = Index + 1\r
-\r
-    if LargestIndex > -1 and not IndexNotFound:\r
-        return os.path.normpath(os.path.join(FilePath, FileName + str(LargestIndex) + '.uni'))\r
-    else:\r
-        return os.path.normpath(os.path.join(FilePath, FileName + '.uni'))\r
diff --git a/BaseTools/Source/Python/UPT/Library/StringUtils.py b/BaseTools/Source/Python/UPT/Library/StringUtils.py
new file mode 100644 (file)
index 0000000..b79891e
--- /dev/null
@@ -0,0 +1,990 @@
+## @file\r
+# This file is used to define common string related functions used in parsing\r
+# process\r
+#\r
+# Copyright (c) 2011 - 2016, 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
+String\r
+'''\r
+##\r
+# Import Modules\r
+#\r
+import re\r
+import os.path\r
+from string import strip\r
+import Logger.Log as Logger\r
+import Library.DataType as DataType\r
+from Logger.ToolError import FORMAT_INVALID\r
+from Logger.ToolError import PARSER_ERROR\r
+from Logger import StringTable as ST\r
+\r
+#\r
+# Regular expression for matching macro used in DSC/DEC/INF file inclusion\r
+#\r
+gMACRO_PATTERN = re.compile("\$\(([_A-Z][_A-Z0-9]*)\)", re.UNICODE)\r
+\r
+## GetSplitValueList\r
+#\r
+# Get a value list from a string with multiple values splited with SplitTag\r
+# The default SplitTag is DataType.TAB_VALUE_SPLIT\r
+# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']\r
+#\r
+# @param String:    The input string to be splitted\r
+# @param SplitTag:  The split key, default is DataType.TAB_VALUE_SPLIT\r
+# @param MaxSplit:  The max number of split values, default is -1\r
+#\r
+#\r
+def GetSplitValueList(String, SplitTag=DataType.TAB_VALUE_SPLIT, MaxSplit= -1):\r
+    return map(lambda l: l.strip(), String.split(SplitTag, MaxSplit))\r
+\r
+## MergeArches\r
+#\r
+# Find a key's all arches in dict, add the new arch to the list\r
+# If not exist any arch, set the arch directly\r
+#\r
+# @param Dict:  The input value for Dict\r
+# @param Key:   The input value for Key\r
+# @param Arch:  The Arch to be added or merged\r
+#\r
+def MergeArches(Dict, Key, Arch):\r
+    if Key in Dict.keys():\r
+        Dict[Key].append(Arch)\r
+    else:\r
+        Dict[Key] = Arch.split()\r
+\r
+## GenDefines\r
+#\r
+# Parse a string with format "DEFINE <VarName> = <PATH>"\r
+# Generate a map Defines[VarName] = PATH\r
+# Return False if invalid format\r
+#\r
+# @param String:   String with DEFINE statement\r
+# @param Arch:     Supportted Arch\r
+# @param Defines:  DEFINE statement to be parsed\r
+#\r
+def GenDefines(String, Arch, Defines):\r
+    if String.find(DataType.TAB_DEFINE + ' ') > -1:\r
+        List = String.replace(DataType.TAB_DEFINE + ' ', '').\\r
+        split(DataType.TAB_EQUAL_SPLIT)\r
+        if len(List) == 2:\r
+            Defines[(CleanString(List[0]), Arch)] = CleanString(List[1])\r
+            return 0\r
+        else:\r
+            return -1\r
+    return 1\r
+\r
+## GetLibraryClassesWithModuleType\r
+#\r
+# Get Library Class definition when no module type defined\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
+def GetLibraryClassesWithModuleType(Lines, Key, KeyValues, CommentCharacter):\r
+    NewKey = SplitModuleType(Key)\r
+    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
+    LineList = Lines.splitlines()\r
+    for Line in LineList:\r
+        Line = CleanString(Line, CommentCharacter)\r
+        if Line != '' and Line[0] != CommentCharacter:\r
+            KeyValues.append([CleanString(Line, CommentCharacter), NewKey[1]])\r
+\r
+    return True\r
+\r
+## GetDynamics\r
+#\r
+# Get Dynamic Pcds\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
+def GetDynamics(Lines, Key, KeyValues, CommentCharacter):\r
+    #\r
+    # Get SkuId Name List\r
+    #\r
+    SkuIdNameList = SplitModuleType(Key)\r
+\r
+    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
+    LineList = Lines.splitlines()\r
+    for Line in LineList:\r
+        Line = CleanString(Line, CommentCharacter)\r
+        if Line != '' and Line[0] != CommentCharacter:\r
+            KeyValues.append([CleanString(Line, CommentCharacter), SkuIdNameList[1]])\r
+\r
+    return True\r
+\r
+## SplitModuleType\r
+#\r
+# Split ModuleType out of section defien to get key\r
+# [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [\r
+# 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]\r
+#\r
+# @param Key:  String to be parsed\r
+#\r
+def SplitModuleType(Key):\r
+    KeyList = Key.split(DataType.TAB_SPLIT)\r
+    #\r
+    # Fill in for arch\r
+    #\r
+    KeyList.append('')\r
+    #\r
+    # Fill in for moduletype\r
+    #\r
+    KeyList.append('')\r
+    ReturnValue = []\r
+    KeyValue = KeyList[0]\r
+    if KeyList[1] != '':\r
+        KeyValue = KeyValue + DataType.TAB_SPLIT + KeyList[1]\r
+    ReturnValue.append(KeyValue)\r
+    ReturnValue.append(GetSplitValueList(KeyList[2]))\r
+\r
+    return ReturnValue\r
+\r
+## Replace macro in string\r
+#\r
+# This method replace macros used in given string. The macros are given in a\r
+# dictionary.\r
+#\r
+# @param String             String to be processed\r
+# @param MacroDefinitions   The macro definitions in the form of dictionary\r
+# @param SelfReplacement    To decide whether replace un-defined macro to ''\r
+# @param Line:              The content contain line string and line number\r
+# @param FileName:        The meta-file file name\r
+#\r
+def ReplaceMacro(String, MacroDefinitions=None, SelfReplacement=False, Line=None, FileName=None, Flag=False):\r
+    LastString = String\r
+    if MacroDefinitions is None:\r
+        MacroDefinitions = {}\r
+    while MacroDefinitions:\r
+        QuotedStringList = []\r
+        HaveQuotedMacroFlag = False\r
+        if not Flag:\r
+            MacroUsed = gMACRO_PATTERN.findall(String)\r
+        else:\r
+            ReQuotedString = re.compile('\"')\r
+            QuotedStringList = ReQuotedString.split(String)\r
+            if len(QuotedStringList) >= 3:\r
+                HaveQuotedMacroFlag = True\r
+            Count = 0\r
+            MacroString = ""\r
+            for QuotedStringItem in QuotedStringList:\r
+                Count += 1\r
+                if Count % 2 != 0:\r
+                    MacroString += QuotedStringItem\r
+\r
+                if Count == len(QuotedStringList) and Count % 2 == 0:\r
+                    MacroString += QuotedStringItem\r
+\r
+            MacroUsed = gMACRO_PATTERN.findall(MacroString)\r
+        #\r
+        # no macro found in String, stop replacing\r
+        #\r
+        if len(MacroUsed) == 0:\r
+            break\r
+        for Macro in MacroUsed:\r
+            if Macro not in MacroDefinitions:\r
+                if SelfReplacement:\r
+                    String = String.replace("$(%s)" % Macro, '')\r
+                    Logger.Debug(5, "Delete undefined MACROs in file %s line %d: %s!" % (FileName, Line[1], Line[0]))\r
+                continue\r
+            if not HaveQuotedMacroFlag:\r
+                String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro])\r
+            else:\r
+                Count = 0\r
+                for QuotedStringItem in QuotedStringList:\r
+                    Count += 1\r
+                    if Count % 2 != 0:\r
+                        QuotedStringList[Count - 1] = QuotedStringList[Count - 1].replace("$(%s)" % Macro,\r
+                                                                        MacroDefinitions[Macro])\r
+                    elif Count == len(QuotedStringList) and Count % 2 == 0:\r
+                        QuotedStringList[Count - 1] = QuotedStringList[Count - 1].replace("$(%s)" % Macro,\r
+                                                                        MacroDefinitions[Macro])\r
+\r
+        RetString = ''\r
+        if HaveQuotedMacroFlag:\r
+            Count = 0\r
+            for QuotedStringItem in QuotedStringList:\r
+                Count += 1\r
+                if Count != len(QuotedStringList):\r
+                    RetString += QuotedStringList[Count - 1] + "\""\r
+                else:\r
+                    RetString += QuotedStringList[Count - 1]\r
+\r
+            String = RetString\r
+\r
+        #\r
+        # in case there's macro not defined\r
+        #\r
+        if String == LastString:\r
+            break\r
+        LastString = String\r
+\r
+    return String\r
+\r
+## NormPath\r
+#\r
+# Create a normal path\r
+# And replace DFEINE in the path\r
+#\r
+# @param Path:     The input value for Path to be converted\r
+# @param Defines:  A set for DEFINE statement\r
+#\r
+def NormPath(Path, Defines=None):\r
+    IsRelativePath = False\r
+    if Defines is None:\r
+        Defines = {}\r
+    if Path:\r
+        if Path[0] == '.':\r
+            IsRelativePath = True\r
+        #\r
+        # Replace with Define\r
+        #\r
+        if Defines:\r
+            Path = ReplaceMacro(Path, Defines)\r
+        #\r
+        # To local path format\r
+        #\r
+        Path = os.path.normpath(Path)\r
+\r
+    if IsRelativePath and Path[0] != '.':\r
+        Path = os.path.join('.', Path)\r
+    return Path\r
+\r
+## CleanString\r
+#\r
+# Remove comments in a string\r
+# Remove spaces\r
+#\r
+# @param Line:              The string to be cleaned\r
+# @param CommentCharacter:  Comment char, used to ignore comment content,\r
+#                           default is DataType.TAB_COMMENT_SPLIT\r
+#\r
+def CleanString(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):\r
+    #\r
+    # remove whitespace\r
+    #\r
+    Line = Line.strip()\r
+    #\r
+    # Replace EDK1's comment character\r
+    #\r
+    if AllowCppStyleComment:\r
+        Line = Line.replace(DataType.TAB_COMMENT_EDK1_SPLIT, CommentCharacter)\r
+    #\r
+    # remove comments, but we should escape comment character in string\r
+    #\r
+    InString = False\r
+    for Index in range(0, len(Line)):\r
+        if Line[Index] == '"':\r
+            InString = not InString\r
+        elif Line[Index] == CommentCharacter and not InString:\r
+            Line = Line[0: Index]\r
+            break\r
+    #\r
+    # remove whitespace again\r
+    #\r
+    Line = Line.strip()\r
+\r
+    return Line\r
+\r
+## CleanString2\r
+#\r
+# Split comments in a string\r
+# Remove spaces\r
+#\r
+# @param Line:              The string to be cleaned\r
+# @param CommentCharacter:  Comment char, used to ignore comment content,\r
+#                           default is DataType.TAB_COMMENT_SPLIT\r
+#\r
+def CleanString2(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):\r
+    #\r
+    # remove whitespace\r
+    #\r
+    Line = Line.strip()\r
+    #\r
+    # Replace EDK1's comment character\r
+    #\r
+    if AllowCppStyleComment:\r
+        Line = Line.replace(DataType.TAB_COMMENT_EDK1_SPLIT, CommentCharacter)\r
+    #\r
+    # separate comments and statements\r
+    #\r
+    LineParts = Line.split(CommentCharacter, 1)\r
+    #\r
+    # remove whitespace again\r
+    #\r
+    Line = LineParts[0].strip()\r
+    if len(LineParts) > 1:\r
+        Comment = LineParts[1].strip()\r
+        #\r
+        # Remove prefixed and trailing comment characters\r
+        #\r
+        Start = 0\r
+        End = len(Comment)\r
+        while Start < End and Comment.startswith(CommentCharacter, Start, End):\r
+            Start += 1\r
+        while End >= 0 and Comment.endswith(CommentCharacter, Start, End):\r
+            End -= 1\r
+        Comment = Comment[Start:End]\r
+        Comment = Comment.strip()\r
+    else:\r
+        Comment = ''\r
+\r
+    return Line, Comment\r
+\r
+## GetMultipleValuesOfKeyFromLines\r
+#\r
+# Parse multiple strings to clean comment and spaces\r
+# The result is saved to KeyValues\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
+def GetMultipleValuesOfKeyFromLines(Lines, Key, KeyValues, CommentCharacter):\r
+    if Key:\r
+        pass\r
+    if KeyValues:\r
+        pass\r
+    Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
+    LineList = Lines.split('\n')\r
+    for Line in LineList:\r
+        Line = CleanString(Line, CommentCharacter)\r
+        if Line != '' and Line[0] != CommentCharacter:\r
+            KeyValues += [Line]\r
+    return True\r
+\r
+## GetDefineValue\r
+#\r
+# Parse a DEFINE statement to get defined value\r
+# DEFINE Key Value\r
+#\r
+# @param String:            The content to be parsed\r
+# @param Key:               The key of DEFINE statement\r
+# @param CommentCharacter:  Comment char, used to ignore comment content\r
+#\r
+def GetDefineValue(String, Key, CommentCharacter):\r
+    if CommentCharacter:\r
+        pass\r
+    String = CleanString(String)\r
+    return String[String.find(Key + ' ') + len(Key + ' ') : ]\r
+\r
+## GetSingleValueOfKeyFromLines\r
+#\r
+# Parse multiple strings as below to get value of each definition line\r
+# Key1 = Value1\r
+# Key2 = Value2\r
+# The result is saved to Dictionary\r
+#\r
+# @param Lines:                The content to be parsed\r
+# @param Dictionary:           To store data after parsing\r
+# @param CommentCharacter:     Comment char, be used to ignore comment content\r
+# @param KeySplitCharacter:    Key split char, between key name and key value.\r
+#                              Key1 = Value1, '=' is the key split char\r
+# @param ValueSplitFlag:       Value split flag, be used to decide if has\r
+#                              multiple values\r
+# @param ValueSplitCharacter:  Value split char, be used to split multiple\r
+#                              values. Key1 = Value1|Value2, '|' is the value\r
+#                              split char\r
+#\r
+def GetSingleValueOfKeyFromLines(Lines, Dictionary, CommentCharacter, KeySplitCharacter, \\r
+                                 ValueSplitFlag, ValueSplitCharacter):\r
+    Lines = Lines.split('\n')\r
+    Keys = []\r
+    Value = ''\r
+    DefineValues = ['']\r
+    SpecValues = ['']\r
+\r
+    for Line in Lines:\r
+        #\r
+        # Handle DEFINE and SPEC\r
+        #\r
+        if Line.find(DataType.TAB_INF_DEFINES_DEFINE + ' ') > -1:\r
+            if '' in DefineValues:\r
+                DefineValues.remove('')\r
+            DefineValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_DEFINE, CommentCharacter))\r
+            continue\r
+        if Line.find(DataType.TAB_INF_DEFINES_SPEC + ' ') > -1:\r
+            if '' in SpecValues:\r
+                SpecValues.remove('')\r
+            SpecValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_SPEC, CommentCharacter))\r
+            continue\r
+\r
+        #\r
+        # Handle Others\r
+        #\r
+        LineList = Line.split(KeySplitCharacter, 1)\r
+        if len(LineList) >= 2:\r
+            Key = LineList[0].split()\r
+            if len(Key) == 1 and Key[0][0] != CommentCharacter:\r
+                #\r
+                # Remove comments and white spaces\r
+                #\r
+                LineList[1] = CleanString(LineList[1], CommentCharacter)\r
+                if ValueSplitFlag:\r
+                    Value = map(strip, LineList[1].split(ValueSplitCharacter))\r
+                else:\r
+                    Value = CleanString(LineList[1], CommentCharacter).splitlines()\r
+\r
+                if Key[0] in Dictionary:\r
+                    if Key[0] not in Keys:\r
+                        Dictionary[Key[0]] = Value\r
+                        Keys.append(Key[0])\r
+                    else:\r
+                        Dictionary[Key[0]].extend(Value)\r
+                else:\r
+                    Dictionary[DataType.TAB_INF_DEFINES_MACRO][Key[0]] = Value[0]\r
+\r
+    if DefineValues == []:\r
+        DefineValues = ['']\r
+    if SpecValues == []:\r
+        SpecValues = ['']\r
+    Dictionary[DataType.TAB_INF_DEFINES_DEFINE] = DefineValues\r
+    Dictionary[DataType.TAB_INF_DEFINES_SPEC] = SpecValues\r
+\r
+    return True\r
+\r
+## The content to be parsed\r
+#\r
+# Do pre-check for a file before it is parsed\r
+# Check $()\r
+# Check []\r
+#\r
+# @param FileName:       Used for error report\r
+# @param FileContent:    File content to be parsed\r
+# @param SupSectionTag:  Used for error report\r
+#\r
+def PreCheck(FileName, FileContent, SupSectionTag):\r
+    if SupSectionTag:\r
+        pass\r
+    LineNo = 0\r
+    IsFailed = False\r
+    NewFileContent = ''\r
+    for Line in FileContent.splitlines():\r
+        LineNo = LineNo + 1\r
+        #\r
+        # Clean current line\r
+        #\r
+        Line = CleanString(Line)\r
+        #\r
+        # Remove commented line\r
+        #\r
+        if Line.find(DataType.TAB_COMMA_SPLIT) == 0:\r
+            Line = ''\r
+        #\r
+        # Check $()\r
+        #\r
+        if Line.find('$') > -1:\r
+            if Line.find('$(') < 0 or Line.find(')') < 0:\r
+                Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)\r
+        #\r
+        # Check []\r
+        #\r
+        if Line.find('[') > -1 or Line.find(']') > -1:\r
+            #\r
+            # Only get one '[' or one ']'\r
+            #\r
+            if not (Line.find('[') > -1 and Line.find(']') > -1):\r
+                Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)\r
+        #\r
+        # Regenerate FileContent\r
+        #\r
+        NewFileContent = NewFileContent + Line + '\r\n'\r
+\r
+    if IsFailed:\r
+        Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)\r
+\r
+    return NewFileContent\r
+\r
+## CheckFileType\r
+#\r
+# Check if the Filename is including ExtName\r
+# Return True if it exists\r
+# Raise a error message if it not exists\r
+#\r
+# @param CheckFilename:      Name of the file to be checked\r
+# @param ExtName:            Ext name of the file to be checked\r
+# @param ContainerFilename:  The container file which describes the file to be\r
+#                            checked, used for error report\r
+# @param SectionName:        Used for error report\r
+# @param Line:               The line in container file which defines the file\r
+#                            to be checked\r
+#\r
+def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo= -1):\r
+    if CheckFilename != '' and CheckFilename is not None:\r
+        (Root, Ext) = os.path.splitext(CheckFilename)\r
+        if Ext.upper() != ExtName.upper() and Root:\r
+            ContainerFile = open(ContainerFilename, 'r').read()\r
+            if LineNo == -1:\r
+                LineNo = GetLineNo(ContainerFile, Line)\r
+            ErrorMsg = ST.ERR_SECTIONNAME_INVALID % (SectionName, CheckFilename, ExtName)\r
+            Logger.Error("Parser", PARSER_ERROR, ErrorMsg, Line=LineNo, \\r
+                         File=ContainerFilename, RaiseError=Logger.IS_RAISE_ERROR)\r
+\r
+    return True\r
+\r
+## CheckFileExist\r
+#\r
+# Check if the file exists\r
+# Return True if it exists\r
+# Raise a error message if it not exists\r
+#\r
+# @param CheckFilename:      Name of the file to be checked\r
+# @param WorkspaceDir:       Current workspace dir\r
+# @param ContainerFilename:  The container file which describes the file to\r
+#                            be checked, used for error report\r
+# @param SectionName:        Used for error report\r
+# @param Line:               The line in container file which defines the\r
+#                            file to be checked\r
+#\r
+def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo= -1):\r
+    CheckFile = ''\r
+    if CheckFilename != '' and CheckFilename is not None:\r
+        CheckFile = WorkspaceFile(WorkspaceDir, CheckFilename)\r
+        if not os.path.isfile(CheckFile):\r
+            ContainerFile = open(ContainerFilename, 'r').read()\r
+            if LineNo == -1:\r
+                LineNo = GetLineNo(ContainerFile, Line)\r
+            ErrorMsg = ST.ERR_CHECKFILE_NOTFOUND % (CheckFile, SectionName)\r
+            Logger.Error("Parser", PARSER_ERROR, ErrorMsg,\r
+                            File=ContainerFilename, Line=LineNo, RaiseError=Logger.IS_RAISE_ERROR)\r
+    return CheckFile\r
+\r
+## GetLineNo\r
+#\r
+# Find the index of a line in a file\r
+#\r
+# @param FileContent:  Search scope\r
+# @param Line:         Search key\r
+#\r
+def GetLineNo(FileContent, Line, IsIgnoreComment=True):\r
+    LineList = FileContent.splitlines()\r
+    for Index in range(len(LineList)):\r
+        if LineList[Index].find(Line) > -1:\r
+            #\r
+            # Ignore statement in comment\r
+            #\r
+            if IsIgnoreComment:\r
+                if LineList[Index].strip()[0] == DataType.TAB_COMMENT_SPLIT:\r
+                    continue\r
+            return Index + 1\r
+\r
+    return -1\r
+\r
+## RaiseParserError\r
+#\r
+# Raise a parser error\r
+#\r
+# @param Line:     String which has error\r
+# @param Section:  Used for error report\r
+# @param File:     File which has the string\r
+# @param Format:   Correct format\r
+#\r
+def RaiseParserError(Line, Section, File, Format='', LineNo= -1):\r
+    if LineNo == -1:\r
+        LineNo = GetLineNo(open(os.path.normpath(File), 'r').read(), Line)\r
+    ErrorMsg = ST.ERR_INVALID_NOTFOUND % (Line, Section)\r
+    if Format != '':\r
+        Format = "Correct format is " + Format\r
+    Logger.Error("Parser", PARSER_ERROR, ErrorMsg, File=File, Line=LineNo, \\r
+                 ExtraData=Format, RaiseError=Logger.IS_RAISE_ERROR)\r
+\r
+## WorkspaceFile\r
+#\r
+# Return a full path with workspace dir\r
+#\r
+# @param WorkspaceDir:  Workspace dir\r
+# @param Filename:      Relative file name\r
+#\r
+def WorkspaceFile(WorkspaceDir, Filename):\r
+    return os.path.join(NormPath(WorkspaceDir), NormPath(Filename))\r
+\r
+## Split string\r
+#\r
+# Revmove '"' which startswith and endswith string\r
+#\r
+# @param String:  The string need to be splited\r
+#\r
+def SplitString(String):\r
+    if String.startswith('\"'):\r
+        String = String[1:]\r
+    if String.endswith('\"'):\r
+        String = String[:-1]\r
+    return String\r
+\r
+## Convert To Sql String\r
+#\r
+# Replace "'" with "''" in each item of StringList\r
+#\r
+# @param StringList:  A list for strings to be converted\r
+#\r
+def ConvertToSqlString(StringList):\r
+    return map(lambda s: s.replace("'", "''") , StringList)\r
+\r
+## Convert To Sql String\r
+#\r
+# Replace "'" with "''" in the String\r
+#\r
+# @param String:  A String to be converted\r
+#\r
+def ConvertToSqlString2(String):\r
+    return String.replace("'", "''")\r
+\r
+## GetStringOfList\r
+#\r
+# Get String of a List\r
+#\r
+# @param Lines: string list\r
+# @param Split: split character\r
+#\r
+def GetStringOfList(List, Split=' '):\r
+    if type(List) != type([]):\r
+        return List\r
+    Str = ''\r
+    for Item in List:\r
+        Str = Str + Item + Split\r
+    return Str.strip()\r
+\r
+## Get HelpTextList\r
+#\r
+# Get HelpTextList from HelpTextClassList\r
+#\r
+# @param HelpTextClassList: Help Text Class List\r
+#\r
+def GetHelpTextList(HelpTextClassList):\r
+    List = []\r
+    if HelpTextClassList:\r
+        for HelpText in HelpTextClassList:\r
+            if HelpText.String.endswith('\n'):\r
+                HelpText.String = HelpText.String[0: len(HelpText.String) - len('\n')]\r
+                List.extend(HelpText.String.split('\n'))\r
+    return List\r
+\r
+## Get String Array Length\r
+#\r
+# Get String Array Length\r
+#\r
+# @param String: the source string\r
+#\r
+def StringArrayLength(String):\r
+    if isinstance(String, unicode):\r
+        return (len(String) + 1) * 2 + 1\r
+    elif String.startswith('L"'):\r
+        return (len(String) - 3 + 1) * 2\r
+    elif String.startswith('"'):\r
+        return (len(String) - 2 + 1)\r
+    else:\r
+        return len(String.split()) + 1\r
+\r
+## RemoveDupOption\r
+#\r
+# Remove Dup Option\r
+#\r
+# @param OptionString: the option string\r
+# @param Which: Which flag\r
+# @param Against: Against flag\r
+#\r
+def RemoveDupOption(OptionString, Which="/I", Against=None):\r
+    OptionList = OptionString.split()\r
+    ValueList = []\r
+    if Against:\r
+        ValueList += Against\r
+    for Index in range(len(OptionList)):\r
+        Opt = OptionList[Index]\r
+        if not Opt.startswith(Which):\r
+            continue\r
+        if len(Opt) > len(Which):\r
+            Val = Opt[len(Which):]\r
+        else:\r
+            Val = ""\r
+        if Val in ValueList:\r
+            OptionList[Index] = ""\r
+        else:\r
+            ValueList.append(Val)\r
+    return " ".join(OptionList)\r
+\r
+## Check if the string is HexDgit\r
+#\r
+# Return true if all characters in the string are digits and there is at\r
+# least one character\r
+# or valid Hexs (started with 0x, following by hexdigit letters)\r
+# , false otherwise.\r
+# @param string: input string\r
+#\r
+def IsHexDigit(Str):\r
+    try:\r
+        int(Str, 10)\r
+        return True\r
+    except ValueError:\r
+        if len(Str) > 2 and Str.upper().startswith('0X'):\r
+            try:\r
+                int(Str, 16)\r
+                return True\r
+            except ValueError:\r
+                return False\r
+    return False\r
+\r
+## Check if the string is HexDgit and its interger value within limit of UINT32\r
+#\r
+# Return true if all characters in the string are digits and there is at\r
+# least one character\r
+# or valid Hexs (started with 0x, following by hexdigit letters)\r
+# , false otherwise.\r
+# @param string: input string\r
+#\r
+def IsHexDigitUINT32(Str):\r
+    try:\r
+        Value = int(Str, 10)\r
+        if (Value <= 0xFFFFFFFF) and (Value >= 0):\r
+            return True\r
+    except ValueError:\r
+        if len(Str) > 2 and Str.upper().startswith('0X'):\r
+            try:\r
+                Value = int(Str, 16)\r
+                if (Value <= 0xFFFFFFFF) and (Value >= 0):\r
+                    return True\r
+            except ValueError:\r
+                return False\r
+    return False\r
+\r
+## CleanSpecialChar\r
+#\r
+# The ASCII text files of type INF, DEC, INI are edited by developers,\r
+# and may contain characters that cannot be directly translated to strings that\r
+# are conformant with the UDP XML Schema.  Any characters in this category\r
+# (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF)\r
+# must be converted to a space character[0x20] as part of the parsing process.\r
+#\r
+def ConvertSpecialChar(Lines):\r
+    RetLines = []\r
+    for line in Lines:\r
+        ReMatchSpecialChar = re.compile(r"[\x00-\x08]|\x09|\x0b|\x0c|[\x0e-\x1f]|[\x7f-\xff]")\r
+        RetLines.append(ReMatchSpecialChar.sub(' ', line))\r
+\r
+    return RetLines\r
+\r
+## __GetTokenList\r
+#\r
+# Assume Str is a valid feature flag expression.\r
+# Return a list which contains tokens: alpha numeric token and other token\r
+# Whitespace are not stripped\r
+#\r
+def __GetTokenList(Str):\r
+    InQuote = False\r
+    Token = ''\r
+    TokenOP = ''\r
+    PreChar = ''\r
+    List = []\r
+    for Char in Str:\r
+        if InQuote:\r
+            Token += Char\r
+            if Char == '"' and PreChar != '\\':\r
+                InQuote = not InQuote\r
+                List.append(Token)\r
+                Token = ''\r
+            continue\r
+        if Char == '"':\r
+            if Token and Token != 'L':\r
+                List.append(Token)\r
+                Token = ''\r
+            if TokenOP:\r
+                List.append(TokenOP)\r
+                TokenOP = ''\r
+            InQuote = not InQuote\r
+            Token += Char\r
+            continue\r
+\r
+        if not (Char.isalnum() or Char in '_'):\r
+            TokenOP += Char\r
+            if Token:\r
+                List.append(Token)\r
+                Token = ''\r
+        else:\r
+            Token += Char\r
+            if TokenOP:\r
+                List.append(TokenOP)\r
+                TokenOP = ''\r
+\r
+        if PreChar == '\\' and Char == '\\':\r
+            PreChar = ''\r
+        else:\r
+            PreChar = Char\r
+    if Token:\r
+        List.append(Token)\r
+    if TokenOP:\r
+        List.append(TokenOP)\r
+    return List\r
+\r
+## ConvertNEToNOTEQ\r
+#\r
+# Convert NE operator to NOT EQ\r
+# For example: 1 NE 2 -> 1 NOT EQ 2\r
+#\r
+# @param Expr: Feature flag expression to be converted\r
+#\r
+def ConvertNEToNOTEQ(Expr):\r
+    List = __GetTokenList(Expr)\r
+    for Index in range(len(List)):\r
+        if List[Index] == 'NE':\r
+            List[Index] = 'NOT EQ'\r
+    return ''.join(List)\r
+\r
+## ConvertNOTEQToNE\r
+#\r
+# Convert NOT EQ operator to NE\r
+# For example: 1 NOT NE 2 -> 1 NE 2\r
+#\r
+# @param Expr: Feature flag expression to be converted\r
+#\r
+def ConvertNOTEQToNE(Expr):\r
+    List = __GetTokenList(Expr)\r
+    HasNOT = False\r
+    RetList = []\r
+    for Token in List:\r
+        if HasNOT and Token == 'EQ':\r
+            # At least, 'NOT' is in the list\r
+            while not RetList[-1].strip():\r
+                RetList.pop()\r
+            RetList[-1] = 'NE'\r
+            HasNOT = False\r
+            continue\r
+        if Token == 'NOT':\r
+            HasNOT = True\r
+        elif Token.strip():\r
+            HasNOT = False\r
+        RetList.append(Token)\r
+\r
+    return ''.join(RetList)\r
+\r
+## SplitPcdEntry\r
+#\r
+# Split an PCD entry string to Token.CName and PCD value and FFE.\r
+# NOTE: PCD Value and FFE can contain "|" in it's expression. And in INF specification, have below rule.\r
+# When using the characters "|" or "||" in an expression, the expression must be encapsulated in\r
+# open "(" and close ")" parenthesis.\r
+#\r
+# @param String    An PCD entry string need to be split.\r
+#\r
+# @return List     [PcdTokenCName, Value, FFE]\r
+#\r
+def SplitPcdEntry(String):\r
+    if not String:\r
+        return ['', '', ''], False\r
+\r
+    PcdTokenCName = ''\r
+    PcdValue = ''\r
+    PcdFeatureFlagExp = ''\r
+\r
+    ValueList = GetSplitValueList(String, "|", 1)\r
+\r
+    #\r
+    # Only contain TokenCName\r
+    #\r
+    if len(ValueList) == 1:\r
+        return [ValueList[0]], True\r
+\r
+    NewValueList = []\r
+\r
+    if len(ValueList) == 2:\r
+        PcdTokenCName = ValueList[0]\r
+\r
+        InQuote = False\r
+        InParenthesis = False\r
+        StrItem = ''\r
+        for StrCh in ValueList[1]:\r
+            if StrCh == '"':\r
+                InQuote = not InQuote\r
+            elif StrCh == '(' or StrCh == ')':\r
+                InParenthesis = not InParenthesis\r
+\r
+            if StrCh == '|':\r
+                if not InQuote or not InParenthesis:\r
+                    NewValueList.append(StrItem.strip())\r
+                    StrItem = ' '\r
+                    continue\r
+\r
+            StrItem += StrCh\r
+\r
+        NewValueList.append(StrItem.strip())\r
+\r
+        if len(NewValueList) == 1:\r
+            PcdValue = NewValueList[0]\r
+            return [PcdTokenCName, PcdValue], True\r
+        elif len(NewValueList) == 2:\r
+            PcdValue = NewValueList[0]\r
+            PcdFeatureFlagExp = NewValueList[1]\r
+            return [PcdTokenCName, PcdValue, PcdFeatureFlagExp], True\r
+        else:\r
+            return ['', '', ''], False\r
+\r
+    return ['', '', ''], False\r
+\r
+## Check if two arches matched?\r
+#\r
+# @param Arch1\r
+# @param Arch2\r
+#\r
+def IsMatchArch(Arch1, Arch2):\r
+    if 'COMMON' in Arch1 or 'COMMON' in Arch2:\r
+        return True\r
+    if isinstance(Arch1, basestring) and isinstance(Arch2, basestring):\r
+        if Arch1 == Arch2:\r
+            return True\r
+\r
+    if isinstance(Arch1, basestring) and isinstance(Arch2, list):\r
+        return Arch1 in Arch2\r
+\r
+    if isinstance(Arch2, basestring) and isinstance(Arch1, list):\r
+        return Arch2 in Arch1\r
+\r
+    if isinstance(Arch1, list) and isinstance(Arch2, list):\r
+        for Item1 in Arch1:\r
+            for Item2 in Arch2:\r
+                if Item1 == Item2:\r
+                    return True\r
+\r
+    return False\r
+\r
+# Search all files in FilePath to find the FileName with the largest index\r
+# Return the FileName with index +1 under the FilePath\r
+#\r
+def GetUniFileName(FilePath, FileName):\r
+    Files = []\r
+    try:\r
+        Files = os.listdir(FilePath)\r
+    except:\r
+        pass\r
+\r
+    LargestIndex = -1\r
+    IndexNotFound = True\r
+    for File in Files:\r
+        if File.upper().startswith(FileName.upper()) and File.upper().endswith('.UNI'):\r
+            Index = File.upper().replace(FileName.upper(), '').replace('.UNI', '')\r
+            if Index:\r
+                try:\r
+                    Index = int(Index)\r
+                except Exception:\r
+                    Index = -1\r
+            else:\r
+                IndexNotFound = False\r
+                Index = 0\r
+            if Index > LargestIndex:\r
+                LargestIndex = Index + 1\r
+\r
+    if LargestIndex > -1 and not IndexNotFound:\r
+        return os.path.normpath(os.path.join(FilePath, FileName + str(LargestIndex) + '.uni'))\r
+    else:\r
+        return os.path.normpath(os.path.join(FilePath, FileName + '.uni'))\r
index 1fbd095f743cf03f4578ca70055de680ea6223dc..99257d08147bc2adf77a5e3995682feb281dd917 100644 (file)
@@ -11,7 +11,7 @@
 # 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
 # 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
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
index 0262a91ed855a055e221812a5152f0cc1fe0aede..1ed7eb1c2cf72983a1c08eb048edf6e985aeca6b 100644 (file)
@@ -17,7 +17,7 @@
 #  This class is used to retrieve information stored in database and convert them\r
 # into PlatformBuildClassObject form for easier use for AutoGen.\r
 #\r
 #  This class is used to retrieve information stored in database and convert them\r
 # into PlatformBuildClassObject form for easier use for AutoGen.\r
 #\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
index bd1c84154123cb310dd693e2cc76e3ae1c8eb642..836140759f2181a9b88180b290e6621c5d4b3993 100644 (file)
@@ -12,7 +12,7 @@
 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 #\r
 \r
 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 #\r
 \r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
index 36843643ed13c2deebae583119e3936834f9794d..8ab1dd23a09621db4c6d2dc4d72823f1fe6d1b20 100644 (file)
@@ -26,7 +26,7 @@ import Common.GlobalData as GlobalData
 \r
 from CommonDataClass.DataClass import *\r
 from Common.DataType import *\r
 \r
 from CommonDataClass.DataClass import *\r
 from Common.DataType import *\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue\r
 from Common.Expression import *\r
 from CommonDataClass.Exceptions import *\r
 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue\r
 from Common.Expression import *\r
 from CommonDataClass.Exceptions import *\r
index 14dcb1ae81361963db3f3e02be489ff8862d9e0c..9e055fcfc46bf8a038827a838c2cb84a5476b36c 100644 (file)
@@ -16,7 +16,7 @@
 # Import Modules\r
 #\r
 import sqlite3\r
 # Import Modules\r
 #\r
 import sqlite3\r
-from Common.String import *\r
+from Common.StringUtils import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
index cf45ef1734981ab2a3d187992b6e6c21222f60ca..3c495a6b1b312a70d1a0c22c62a498a5d52f0386 100644 (file)
@@ -42,7 +42,7 @@ from Common.MultipleWorkspace import MultipleWorkspace as mws
 import Common.GlobalData as GlobalData\r
 from AutoGen.AutoGen import ModuleAutoGen\r
 from Common.Misc import PathClass\r
 import Common.GlobalData as GlobalData\r
 from AutoGen.AutoGen import ModuleAutoGen\r
 from Common.Misc import PathClass\r
-from Common.String import NormPath\r
+from Common.StringUtils import NormPath\r
 from Common.DataType import *\r
 import collections\r
 from Common.Expression import *\r
 from Common.DataType import *\r
 import collections\r
 from Common.Expression import *\r