X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FString.py;h=a35f728dc0151c0ade819c93ffc4606ab019260d;hb=0d2711a69397d2971079121df4326d84736c181e;hp=896fb7da0fb9cd14d60b422267cf72429a276dc8;hpb=9053bc517ea77b9780830bf08b966979eff1cb0f;p=mirror_edk2.git diff --git a/BaseTools/Source/Python/Common/String.py b/BaseTools/Source/Python/Common/String.py index 896fb7da0f..a35f728dc0 100644 --- a/BaseTools/Source/Python/Common/String.py +++ b/BaseTools/Source/Python/Common/String.py @@ -20,8 +20,12 @@ import os.path import string import EdkLogger as EdkLogger -from GlobalData import * +import GlobalData from BuildToolError import * +from CommonDataClass.Exceptions import * + +gHexVerPatt = re.compile('0x[a-f0-9]{4}[a-f0-9]{4}$',re.IGNORECASE) +gHumanReadableVerPatt = re.compile(r'([1-9][0-9]*|0)\.[0-9]{1,2}$') ## GetSplitValueList # @@ -36,7 +40,52 @@ from BuildToolError import * # @retval list() A list for splitted string # def GetSplitValueList(String, SplitTag = DataType.TAB_VALUE_SPLIT, MaxSplit = -1): - return map(lambda l: l.strip(), String.split(SplitTag, MaxSplit)) + ValueList = [] + Last = 0 + Escaped = False + InString = False + for Index in range(0, len(String)): + Char = String[Index] + + if not Escaped: + # Found a splitter not in a string, split it + if not InString and Char == SplitTag: + ValueList.append(String[Last:Index].strip()) + Last = Index+1 + if MaxSplit > 0 and len(ValueList) >= MaxSplit: + break + + if Char == '\\' and InString: + Escaped = True + elif Char == '"': + if not InString: + InString = True + else: + InString = False + else: + Escaped = False + + if Last < len(String): + ValueList.append(String[Last:].strip()) + elif Last == len(String): + ValueList.append('') + + return ValueList + +## GetSplitList +# +# Get a value list from a string with multiple values splited with SplitString +# The default SplitTag is DataType.TAB_VALUE_SPLIT +# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC'] +# +# @param String: The input string to be splitted +# @param SplitStr: The split key, default is DataType.TAB_VALUE_SPLIT +# @param MaxSplit: The max number of split values, default is -1 +# +# @retval list() A list for splitted string +# +def GetSplitList(String, SplitStr = DataType.TAB_VALUE_SPLIT, MaxSplit = -1): + return map(lambda l: l.strip(), String.split(SplitStr, MaxSplit)) ## MergeArches # @@ -207,16 +256,18 @@ def ReplaceMacros(StringList, MacroDefinitions={}, SelfReplacement = False): # # @retval string The string whose macros are replaced # -def ReplaceMacro(String, MacroDefinitions={}, SelfReplacement = False): +def ReplaceMacro(String, MacroDefinitions={}, SelfReplacement=False, RaiseError=False): LastString = String - while MacroDefinitions: - MacroUsed = gMacroPattern.findall(String) + while String and MacroDefinitions: + MacroUsed = GlobalData.gMacroRefPattern.findall(String) # no macro found in String, stop replacing if len(MacroUsed) == 0: break for Macro in MacroUsed: if Macro not in MacroDefinitions: + if RaiseError: + raise SymbolNotFound("%s not defined" % Macro) if SelfReplacement: String = String.replace("$(%s)" % Macro, '') continue @@ -274,21 +325,40 @@ def CleanString(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT, AllowCppSty # Line = Line.strip(); # - # Replace R8's comment character + # Replace Edk's comment character # if AllowCppStyleComment: - Line = Line.replace(DataType.TAB_COMMENT_R8_SPLIT, CommentCharacter) + Line = Line.replace(DataType.TAB_COMMENT_EDK_SPLIT, CommentCharacter) # # remove comments, but we should escape comment character in string # InString = False + CommentInString = False for Index in range(0, len(Line)): if Line[Index] == '"': InString = not InString - elif Line[Index] == CommentCharacter and not InString: + elif Line[Index] == CommentCharacter and InString : + CommentInString = True + elif Line[Index] == CommentCharacter and not InString : Line = Line[0: Index] break - + + if CommentInString: + Line = Line.replace('"', '') + ChIndex = Line.find('#') + while ChIndex >= 0: + if GlobalData.gIsWindows: + if ChIndex == 0 or Line[ChIndex-1] != '^': + Line = Line[0:ChIndex] + '^' + Line[ChIndex:] + ChIndex = Line.find('#', ChIndex + 2) + else: + ChIndex = Line.find('#', ChIndex + 1) + else: + if ChIndex == 0 or Line[ChIndex-1] != '\\': + Line = Line[0:ChIndex] + '\\' + Line[ChIndex:] + ChIndex = Line.find('#', ChIndex + 2) + else: + ChIndex = Line.find('#', ChIndex + 1) # # remove whitespace again # @@ -296,6 +366,50 @@ def CleanString(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT, AllowCppSty return Line +## CleanString2 +# +# Split comments in a string +# Remove spaces +# +# @param Line: The string to be cleaned +# @param CommentCharacter: Comment char, used to ignore comment content, default is DataType.TAB_COMMENT_SPLIT +# +# @retval Path Formatted path +# +def CleanString2(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False): + # + # remove whitespace + # + Line = Line.strip(); + # + # Replace Edk's comment character + # + if AllowCppStyleComment: + Line = Line.replace(DataType.TAB_COMMENT_EDK_SPLIT, CommentCharacter) + # + # separate comments and statements + # + LineParts = Line.split(CommentCharacter, 1); + # + # remove whitespace again + # + Line = LineParts[0].strip(); + if len(LineParts) > 1: + Comment = LineParts[1].strip() + # Remove prefixed and trailing comment characters + Start = 0 + End = len(Comment) + while Start < End and Comment.startswith(CommentCharacter, Start, End): + Start += 1 + while End >= 0 and Comment.endswith(CommentCharacter, Start, End): + End -= 1 + Comment = Comment[Start:End] + Comment = Comment.strip() + else: + Comment = '' + + return Line, Comment + ## GetMultipleValuesOfKeyFromLines # # Parse multiple strings to clean comment and spaces @@ -333,6 +447,34 @@ def GetDefineValue(String, Key, CommentCharacter): String = CleanString(String) return String[String.find(Key + ' ') + len(Key + ' ') : ] +## GetHexVerValue +# +# Get a Hex Version Value +# +# @param VerString: The version string to be parsed +# +# +# @retval: If VerString is incorrectly formatted, return "None" which will break the build. +# If VerString is correctly formatted, return a Hex value of the Version Number (0xmmmmnnnn) +# where mmmm is the major number and nnnn is the adjusted minor number. +# +def GetHexVerValue(VerString): + VerString = CleanString(VerString) + + if gHumanReadableVerPatt.match(VerString): + ValueList = VerString.split('.') + Major = ValueList[0] + Minor = ValueList[1] + if len(Minor) == 1: + Minor += '0' + DeciValue = (int(Major) << 16) + int(Minor); + return "0x%08x"%DeciValue + elif gHexVerPatt.match(VerString): + return VerString + else: + return None + + ## GetSingleValueOfKeyFromLines # # Parse multiple strings as below to get value of each definition line @@ -614,11 +756,11 @@ def RemoveBlockComment(Lines): # # Remove comment block # - if Line.find(DataType.TAB_COMMENT_R8_START) > -1: - ReservedLine = GetSplitValueList(Line, DataType.TAB_COMMENT_R8_START, 1)[0] + if Line.find(DataType.TAB_COMMENT_EDK_START) > -1: + ReservedLine = GetSplitValueList(Line, DataType.TAB_COMMENT_EDK_START, 1)[0] IsFindBlockComment = True - if Line.find(DataType.TAB_COMMENT_R8_END) > -1: - Line = ReservedLine + GetSplitValueList(Line, DataType.TAB_COMMENT_R8_END, 1)[1] + if Line.find(DataType.TAB_COMMENT_EDK_END) > -1: + Line = ReservedLine + GetSplitValueList(Line, DataType.TAB_COMMENT_EDK_END, 1)[1] ReservedLine = '' IsFindBlockComment = False if IsFindBlockComment: