X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FString.py;h=4a8c03e88e28297e7c158fc27a420f0851e22d62;hb=97058144294759ffb64005a8543d5dd9a5bdc1fc;hp=195fa5c6cacc0c9d82f483ace03316d04ae67ac2;hpb=08dd311f5dc735c595d39faf2e6f7e2810bb79a9;p=mirror_edk2.git
diff --git a/BaseTools/Source/Python/Common/String.py b/BaseTools/Source/Python/Common/String.py
index 195fa5c6ca..4a8c03e88e 100644
--- a/BaseTools/Source/Python/Common/String.py
+++ b/BaseTools/Source/Python/Common/String.py
@@ -1,7 +1,7 @@
## @file
# This file is used to define common string related functions used in parsing process
#
-# Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
@@ -16,14 +16,17 @@
#
import re
import DataType
-import os.path
+import Common.LongFilePathOs as os
import string
import EdkLogger as EdkLogger
-from GlobalData import *
+import GlobalData
from BuildToolError import *
+from CommonDataClass.Exceptions import *
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
-gHexVerPatt = re.compile('0x[a-f0-9]{4}[a-f0-9]{4}$',re.IGNORECASE)
+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
@@ -38,8 +41,58 @@ gHumanReadableVerPatt = re.compile(r'([1-9][0-9]*|0)\.[0-9]{1,2}$')
#
# @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))
+def GetSplitValueList(String, SplitTag=DataType.TAB_VALUE_SPLIT, MaxSplit= -1):
+ ValueList = []
+ Last = 0
+ Escaped = False
+ InString = False
+ InParenthesis = 0
+ 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 InParenthesis == 0 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
+ elif Char == '(':
+ InParenthesis = InParenthesis + 1
+ elif Char == ')':
+ InParenthesis = InParenthesis - 1
+ 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
#
@@ -189,7 +242,7 @@ def SplitModuleType(Key):
#
# @retval NewList A new string list whose macros are replaced
#
-def ReplaceMacros(StringList, MacroDefinitions={}, SelfReplacement = False):
+def ReplaceMacros(StringList, MacroDefinitions={}, SelfReplacement=False):
NewList = []
for String in StringList:
if type(String) == type(''):
@@ -210,20 +263,23 @@ 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
- String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro])
+ if "$(%s)" % Macro not in MacroDefinitions[Macro]:
+ String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro])
# in case there's macro not defined
if String == LastString:
break
@@ -241,7 +297,7 @@ def ReplaceMacro(String, MacroDefinitions={}, SelfReplacement = False):
#
# @retval Path Formatted path
#
-def NormPath(Path, Defines = {}):
+def NormPath(Path, Defines={}):
IsRelativePath = False
if Path:
if Path[0] == '.':
@@ -255,6 +311,11 @@ def NormPath(Path, Defines = {}):
# To local path format
#
Path = os.path.normpath(Path)
+ if Path.startswith(GlobalData.gWorkspace) and not Path.startswith(GlobalData.gBuildDirectory) and not os.path.exists(Path):
+ Path = Path[len (GlobalData.gWorkspace):]
+ if Path[0] == os.path.sep:
+ Path = Path[1:]
+ Path = mws.join(GlobalData.gWorkspace, Path)
if IsRelativePath and Path[0] != '.':
Path = os.path.join('.', Path)
@@ -271,27 +332,46 @@ def NormPath(Path, Defines = {}):
#
# @retval Path Formatted path
#
-def CleanString(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):
+def CleanString(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False, BuildOption=False):
#
# remove whitespace
#
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 and BuildOption:
+ 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
#
@@ -301,7 +381,7 @@ def CleanString(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT, AllowCppSty
## CleanString2
#
-# Split comments in a string
+# Split statement with comments in a string
# Remove spaces
#
# @param Line: The string to be cleaned
@@ -309,37 +389,31 @@ def CleanString(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT, AllowCppSty
#
# @retval Path Formatted path
#
-def CleanString2(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):
+def CleanString2(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):
#
# remove whitespace
#
Line = Line.strip();
#
- # Replace R8's comment character
+ # Replace Edk's comment character
#
if AllowCppStyleComment:
- Line = Line.replace(DataType.TAB_COMMENT_R8_SPLIT, CommentCharacter)
- #
- # separate comments and statements
+ Line = Line.replace(DataType.TAB_COMMENT_EDK_SPLIT, CommentCharacter)
#
- LineParts = Line.split(CommentCharacter, 1);
+ # separate comments and statements, but we should escape comment character in string
#
- # 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 = ''
+ InString = False
+ CommentInString = False
+ Comment = ''
+ for Index in range(0, len(Line)):
+ if Line[Index] == '"':
+ InString = not InString
+ elif Line[Index] == CommentCharacter and InString:
+ CommentInString = True
+ elif Line[Index] == CommentCharacter and not InString:
+ Comment = Line[Index:].strip()
+ Line = Line[0:Index].strip()
+ break
return Line, Comment
@@ -401,7 +475,7 @@ def GetHexVerValue(VerString):
if len(Minor) == 1:
Minor += '0'
DeciValue = (int(Major) << 16) + int(Minor);
- return "0x%08x"%DeciValue
+ return "0x%08x" % DeciValue
elif gHexVerPatt.match(VerString):
return VerString
else:
@@ -511,7 +585,7 @@ def PreCheck(FileName, FileContent, SupSectionTag):
#
if Line.find('$') > -1:
if Line.find('$(') < 0 or Line.find(')') < 0:
- EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = EdkLogger.IsRaiseError)
+ EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)
#
# Check []
@@ -521,7 +595,7 @@ def PreCheck(FileName, FileContent, SupSectionTag):
# Only get one '[' or one ']'
#
if not (Line.find('[') > -1 and Line.find(']') > -1):
- EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = EdkLogger.IsRaiseError)
+ EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)
#
# Regenerate FileContent
@@ -529,7 +603,7 @@ def PreCheck(FileName, FileContent, SupSectionTag):
NewFileContent = NewFileContent + Line + '\r\n'
if IsFailed:
- EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = EdkLogger.IsRaiseError)
+ EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=EdkLogger.IsRaiseError)
return NewFileContent
@@ -547,7 +621,7 @@ def PreCheck(FileName, FileContent, SupSectionTag):
#
# @retval True The file type is correct
#
-def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo = -1):
+def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo= -1):
if CheckFilename != '' and CheckFilename != None:
(Root, Ext) = os.path.splitext(CheckFilename)
if Ext.upper() != ExtName.upper():
@@ -556,7 +630,7 @@ def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line,
LineNo = GetLineNo(ContainerFile, Line)
ErrorMsg = "Invalid %s. '%s' is found, but '%s' file is needed" % (SectionName, CheckFilename, ExtName)
EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, Line=LineNo,
- File=ContainerFilename, RaiseError = EdkLogger.IsRaiseError)
+ File=ContainerFilename, RaiseError=EdkLogger.IsRaiseError)
return True
@@ -574,7 +648,7 @@ def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line,
#
# @retval The file full path if the file exists
#
-def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo = -1):
+def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo= -1):
CheckFile = ''
if CheckFilename != '' and CheckFilename != None:
CheckFile = WorkspaceFile(WorkspaceDir, CheckFilename)
@@ -584,7 +658,7 @@ def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName,
LineNo = GetLineNo(ContainerFile, Line)
ErrorMsg = "Can't find file '%s' defined in section '%s'" % (CheckFile, SectionName)
EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg,
- File=ContainerFilename, Line = LineNo, RaiseError = EdkLogger.IsRaiseError)
+ File=ContainerFilename, Line=LineNo, RaiseError=EdkLogger.IsRaiseError)
return CheckFile
@@ -598,7 +672,7 @@ def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName,
# @retval int Index of the line
# @retval -1 The line is not found
#
-def GetLineNo(FileContent, Line, IsIgnoreComment = True):
+def GetLineNo(FileContent, Line, IsIgnoreComment=True):
LineList = FileContent.splitlines()
for Index in range(len(LineList)):
if LineList[Index].find(Line) > -1:
@@ -621,13 +695,13 @@ def GetLineNo(FileContent, Line, IsIgnoreComment = True):
# @param File: File which has the string
# @param Format: Correct format
#
-def RaiseParserError(Line, Section, File, Format = '', LineNo = -1):
+def RaiseParserError(Line, Section, File, Format='', LineNo= -1):
if LineNo == -1:
LineNo = GetLineNo(open(os.path.normpath(File), 'r').read(), Line)
ErrorMsg = "Invalid statement '%s' is found in section '%s'" % (Line, Section)
if Format != '':
Format = "Correct format is " + Format
- EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=File, Line=LineNo, ExtraData=Format, RaiseError = EdkLogger.IsRaiseError)
+ EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=File, Line=LineNo, ExtraData=Format, RaiseError=EdkLogger.IsRaiseError)
## WorkspaceFile
#
@@ -639,7 +713,7 @@ def RaiseParserError(Line, Section, File, Format = '', LineNo = -1):
# @retval string A full path
#
def WorkspaceFile(WorkspaceDir, Filename):
- return os.path.join(NormPath(WorkspaceDir), NormPath(Filename))
+ return mws.join(NormPath(WorkspaceDir), NormPath(Filename))
## Split string
#
@@ -689,11 +763,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 = GetSplitList(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 + GetSplitList(Line, DataType.TAB_COMMENT_EDK_END, 1)[1]
ReservedLine = ''
IsFindBlockComment = False
if IsFindBlockComment:
@@ -706,7 +780,7 @@ def RemoveBlockComment(Lines):
#
# Get String of a List
#
-def GetStringOfList(List, Split = ' '):
+def GetStringOfList(List, Split=' '):
if type(List) != type([]):
return List
Str = ''
@@ -730,7 +804,7 @@ def GetHelpTextList(HelpTextClassList):
def StringToArray(String):
if isinstance(String, unicode):
- if len(unicode) ==0:
+ if len(unicode) == 0:
return "{0x00, 0x00}"
return "{%s, 0x00, 0x00}" % ", ".join(["0x%02x, 0x00" % ord(C) for C in String])
elif String.startswith('L"'):
@@ -740,11 +814,25 @@ def StringToArray(String):
return "{%s, 0x00, 0x00}" % ", ".join(["0x%02x, 0x00" % ord(C) for C in String[2:-1]])
elif String.startswith('"'):
if String == "\"\"":
- return "{0x00}";
+ return "{0x00,0x00}"
+ else:
+ StringLen = len(String[1:-1])
+ if StringLen % 2:
+ return "{%s, 0x00}" % ", ".join(["0x%02x" % ord(C) for C in String[1:-1]])
+ else:
+ return "{%s, 0x00,0x00}" % ", ".join(["0x%02x" % ord(C) for C in String[1:-1]])
+ elif String.startswith('{'):
+ StringLen = len(String.split(","))
+ if StringLen % 2:
+ return "{%s, 0x00}" % ", ".join([ C for C in String[1:-1].split(',')])
else:
- return "{%s, 0x00}" % ", ".join(["0x%02x" % ord(C) for C in String[1:-1]])
+ return "{%s}" % ", ".join([ C for C in String[1:-1].split(',')])
+
else:
- return '{%s, 0}' % ', '.join(String.split())
+ if len(String.split()) % 2:
+ return '{%s, 0}' % ', '.join(String.split())
+ else:
+ return '{%s, 0,0}' % ', '.join(String.split())
def StringArrayLength(String):
if isinstance(String, unicode):
@@ -755,7 +843,7 @@ def StringArrayLength(String):
return (len(String) - 2 + 1)
else:
return len(String.split()) + 1
-
+
def RemoveDupOption(OptionString, Which="/I", Against=None):
OptionList = OptionString.split()
ValueList = []