]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Library/StringUtils.py
2 # This file is used to define common string related functions used in parsing
5 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
7 # This program and the accompanying materials are licensed and made available
8 # under the terms and conditions of the BSD License which accompanies this
9 # distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 import Logger
.Log
as Logger
24 import Library
.DataType
as DataType
25 from Logger
.ToolError
import FORMAT_INVALID
26 from Logger
.ToolError
import PARSER_ERROR
27 from Logger
import StringTable
as ST
30 # Regular expression for matching macro used in DSC/DEC/INF file inclusion
32 gMACRO_PATTERN
= re
.compile("\$\(([_A-Z][_A-Z0-9]*)\)", re
.UNICODE
)
36 # Get a value list from a string with multiple values split with SplitTag
37 # The default SplitTag is DataType.TAB_VALUE_SPLIT
38 # 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']
40 # @param String: The input string to be splitted
41 # @param SplitTag: The split key, default is DataType.TAB_VALUE_SPLIT
42 # @param MaxSplit: The max number of split values, default is -1
45 def GetSplitValueList(String
, SplitTag
=DataType
.TAB_VALUE_SPLIT
, MaxSplit
= -1):
46 return list(map(lambda l
: l
.strip(), String
.split(SplitTag
, MaxSplit
)))
50 # Find a key's all arches in dict, add the new arch to the list
51 # If not exist any arch, set the arch directly
53 # @param Dict: The input value for Dict
54 # @param Key: The input value for Key
55 # @param Arch: The Arch to be added or merged
57 def MergeArches(Dict
, Key
, Arch
):
58 if Key
in Dict
.keys():
59 Dict
[Key
].append(Arch
)
61 Dict
[Key
] = Arch
.split()
65 # Parse a string with format "DEFINE <VarName> = <PATH>"
66 # Generate a map Defines[VarName] = PATH
67 # Return False if invalid format
69 # @param String: String with DEFINE statement
70 # @param Arch: Supported Arch
71 # @param Defines: DEFINE statement to be parsed
73 def GenDefines(String
, Arch
, Defines
):
74 if String
.find(DataType
.TAB_DEFINE
+ ' ') > -1:
75 List
= String
.replace(DataType
.TAB_DEFINE
+ ' ', '').\
76 split(DataType
.TAB_EQUAL_SPLIT
)
78 Defines
[(CleanString(List
[0]), Arch
)] = CleanString(List
[1])
84 ## GetLibraryClassesWithModuleType
86 # Get Library Class definition when no module type defined
88 # @param Lines: The content to be parsed
89 # @param Key: Reserved
90 # @param KeyValues: To store data after parsing
91 # @param CommentCharacter: Comment char, used to ignore comment content
93 def GetLibraryClassesWithModuleType(Lines
, Key
, KeyValues
, CommentCharacter
):
94 NewKey
= SplitModuleType(Key
)
95 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
96 LineList
= Lines
.splitlines()
98 Line
= CleanString(Line
, CommentCharacter
)
99 if Line
!= '' and Line
[0] != CommentCharacter
:
100 KeyValues
.append([CleanString(Line
, CommentCharacter
), NewKey
[1]])
108 # @param Lines: The content to be parsed
109 # @param Key: Reserved
110 # @param KeyValues: To store data after parsing
111 # @param CommentCharacter: Comment char, used to ignore comment content
113 def GetDynamics(Lines
, Key
, KeyValues
, CommentCharacter
):
115 # Get SkuId Name List
117 SkuIdNameList
= SplitModuleType(Key
)
119 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
120 LineList
= Lines
.splitlines()
121 for Line
in LineList
:
122 Line
= CleanString(Line
, CommentCharacter
)
123 if Line
!= '' and Line
[0] != CommentCharacter
:
124 KeyValues
.append([CleanString(Line
, CommentCharacter
), SkuIdNameList
[1]])
130 # Split ModuleType out of section defien to get key
131 # [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [
132 # 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]
134 # @param Key: String to be parsed
136 def SplitModuleType(Key
):
137 KeyList
= Key
.split(DataType
.TAB_SPLIT
)
143 # Fill in for moduletype
147 KeyValue
= KeyList
[0]
149 KeyValue
= KeyValue
+ DataType
.TAB_SPLIT
+ KeyList
[1]
150 ReturnValue
.append(KeyValue
)
151 ReturnValue
.append(GetSplitValueList(KeyList
[2]))
155 ## Replace macro in string
157 # This method replace macros used in given string. The macros are given in a
160 # @param String String to be processed
161 # @param MacroDefinitions The macro definitions in the form of dictionary
162 # @param SelfReplacement To decide whether replace un-defined macro to ''
163 # @param Line: The content contain line string and line number
164 # @param FileName: The meta-file file name
166 def ReplaceMacro(String
, MacroDefinitions
=None, SelfReplacement
=False, Line
=None, FileName
=None, Flag
=False):
168 if MacroDefinitions
is None:
169 MacroDefinitions
= {}
170 while MacroDefinitions
:
171 QuotedStringList
= []
172 HaveQuotedMacroFlag
= False
174 MacroUsed
= gMACRO_PATTERN
.findall(String
)
176 ReQuotedString
= re
.compile('\"')
177 QuotedStringList
= ReQuotedString
.split(String
)
178 if len(QuotedStringList
) >= 3:
179 HaveQuotedMacroFlag
= True
182 for QuotedStringItem
in QuotedStringList
:
185 MacroString
+= QuotedStringItem
187 if Count
== len(QuotedStringList
) and Count
% 2 == 0:
188 MacroString
+= QuotedStringItem
190 MacroUsed
= gMACRO_PATTERN
.findall(MacroString
)
192 # no macro found in String, stop replacing
194 if len(MacroUsed
) == 0:
196 for Macro
in MacroUsed
:
197 if Macro
not in MacroDefinitions
:
199 String
= String
.replace("$(%s)" % Macro
, '')
200 Logger
.Debug(5, "Delete undefined MACROs in file %s line %d: %s!" % (FileName
, Line
[1], Line
[0]))
202 if not HaveQuotedMacroFlag
:
203 String
= String
.replace("$(%s)" % Macro
, MacroDefinitions
[Macro
])
206 for QuotedStringItem
in QuotedStringList
:
209 QuotedStringList
[Count
- 1] = QuotedStringList
[Count
- 1].replace("$(%s)" % Macro
,
210 MacroDefinitions
[Macro
])
211 elif Count
== len(QuotedStringList
) and Count
% 2 == 0:
212 QuotedStringList
[Count
- 1] = QuotedStringList
[Count
- 1].replace("$(%s)" % Macro
,
213 MacroDefinitions
[Macro
])
216 if HaveQuotedMacroFlag
:
218 for QuotedStringItem
in QuotedStringList
:
220 if Count
!= len(QuotedStringList
):
221 RetString
+= QuotedStringList
[Count
- 1] + "\""
223 RetString
+= QuotedStringList
[Count
- 1]
228 # in case there's macro not defined
230 if String
== LastString
:
238 # Create a normal path
239 # And replace DEFINE in the path
241 # @param Path: The input value for Path to be converted
242 # @param Defines: A set for DEFINE statement
244 def NormPath(Path
, Defines
=None):
245 IsRelativePath
= False
250 IsRelativePath
= True
252 # Replace with Define
255 Path
= ReplaceMacro(Path
, Defines
)
257 # To local path format
259 Path
= os
.path
.normpath(Path
)
261 if IsRelativePath
and Path
[0] != '.':
262 Path
= os
.path
.join('.', Path
)
267 # Remove comments in a string
270 # @param Line: The string to be cleaned
271 # @param CommentCharacter: Comment char, used to ignore comment content,
272 # default is DataType.TAB_COMMENT_SPLIT
274 def CleanString(Line
, CommentCharacter
=DataType
.TAB_COMMENT_SPLIT
, AllowCppStyleComment
=False):
280 # Replace EDK1's comment character
282 if AllowCppStyleComment
:
283 Line
= Line
.replace(DataType
.TAB_COMMENT_EDK1_SPLIT
, CommentCharacter
)
285 # remove comments, but we should escape comment character in string
288 for Index
in range(0, len(Line
)):
289 if Line
[Index
] == '"':
290 InString
= not InString
291 elif Line
[Index
] == CommentCharacter
and not InString
:
292 Line
= Line
[0: Index
]
295 # remove whitespace again
303 # Split comments in a string
306 # @param Line: The string to be cleaned
307 # @param CommentCharacter: Comment char, used to ignore comment content,
308 # default is DataType.TAB_COMMENT_SPLIT
310 def CleanString2(Line
, CommentCharacter
=DataType
.TAB_COMMENT_SPLIT
, AllowCppStyleComment
=False):
316 # Replace EDK1's comment character
318 if AllowCppStyleComment
:
319 Line
= Line
.replace(DataType
.TAB_COMMENT_EDK1_SPLIT
, CommentCharacter
)
321 # separate comments and statements
323 LineParts
= Line
.split(CommentCharacter
, 1)
325 # remove whitespace again
327 Line
= LineParts
[0].strip()
328 if len(LineParts
) > 1:
329 Comment
= LineParts
[1].strip()
331 # Remove prefixed and trailing comment characters
335 while Start
< End
and Comment
.startswith(CommentCharacter
, Start
, End
):
337 while End
>= 0 and Comment
.endswith(CommentCharacter
, Start
, End
):
339 Comment
= Comment
[Start
:End
]
340 Comment
= Comment
.strip()
346 ## GetMultipleValuesOfKeyFromLines
348 # Parse multiple strings to clean comment and spaces
349 # The result is saved to KeyValues
351 # @param Lines: The content to be parsed
352 # @param Key: Reserved
353 # @param KeyValues: To store data after parsing
354 # @param CommentCharacter: Comment char, used to ignore comment content
356 def GetMultipleValuesOfKeyFromLines(Lines
, Key
, KeyValues
, CommentCharacter
):
361 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
362 LineList
= Lines
.split('\n')
363 for Line
in LineList
:
364 Line
= CleanString(Line
, CommentCharacter
)
365 if Line
!= '' and Line
[0] != CommentCharacter
:
371 # Parse a DEFINE statement to get defined value
374 # @param String: The content to be parsed
375 # @param Key: The key of DEFINE statement
376 # @param CommentCharacter: Comment char, used to ignore comment content
378 def GetDefineValue(String
, Key
, CommentCharacter
):
381 String
= CleanString(String
)
382 return String
[String
.find(Key
+ ' ') + len(Key
+ ' ') : ]
384 ## GetSingleValueOfKeyFromLines
386 # Parse multiple strings as below to get value of each definition line
389 # The result is saved to Dictionary
391 # @param Lines: The content to be parsed
392 # @param Dictionary: To store data after parsing
393 # @param CommentCharacter: Comment char, be used to ignore comment content
394 # @param KeySplitCharacter: Key split char, between key name and key value.
395 # Key1 = Value1, '=' is the key split char
396 # @param ValueSplitFlag: Value split flag, be used to decide if has
398 # @param ValueSplitCharacter: Value split char, be used to split multiple
399 # values. Key1 = Value1|Value2, '|' is the value
402 def GetSingleValueOfKeyFromLines(Lines
, Dictionary
, CommentCharacter
, KeySplitCharacter
, \
403 ValueSplitFlag
, ValueSplitCharacter
):
404 Lines
= Lines
.split('\n')
412 # Handle DEFINE and SPEC
414 if Line
.find(DataType
.TAB_INF_DEFINES_DEFINE
+ ' ') > -1:
415 if '' in DefineValues
:
416 DefineValues
.remove('')
417 DefineValues
.append(GetDefineValue(Line
, DataType
.TAB_INF_DEFINES_DEFINE
, CommentCharacter
))
419 if Line
.find(DataType
.TAB_INF_DEFINES_SPEC
+ ' ') > -1:
421 SpecValues
.remove('')
422 SpecValues
.append(GetDefineValue(Line
, DataType
.TAB_INF_DEFINES_SPEC
, CommentCharacter
))
428 LineList
= Line
.split(KeySplitCharacter
, 1)
429 if len(LineList
) >= 2:
430 Key
= LineList
[0].split()
431 if len(Key
) == 1 and Key
[0][0] != CommentCharacter
:
433 # Remove comments and white spaces
435 LineList
[1] = CleanString(LineList
[1], CommentCharacter
)
437 Value
= list(map(lambda x
: x
.strip(), LineList
[1].split(ValueSplitCharacter
)))
439 Value
= CleanString(LineList
[1], CommentCharacter
).splitlines()
441 if Key
[0] in Dictionary
:
442 if Key
[0] not in Keys
:
443 Dictionary
[Key
[0]] = Value
446 Dictionary
[Key
[0]].extend(Value
)
448 Dictionary
[DataType
.TAB_INF_DEFINES_MACRO
][Key
[0]] = Value
[0]
450 if DefineValues
== []:
454 Dictionary
[DataType
.TAB_INF_DEFINES_DEFINE
] = DefineValues
455 Dictionary
[DataType
.TAB_INF_DEFINES_SPEC
] = SpecValues
459 ## The content to be parsed
461 # Do pre-check for a file before it is parsed
465 # @param FileName: Used for error report
466 # @param FileContent: File content to be parsed
467 # @param SupSectionTag: Used for error report
469 def PreCheck(FileName
, FileContent
, SupSectionTag
):
475 for Line
in FileContent
.splitlines():
480 Line
= CleanString(Line
)
482 # Remove commented line
484 if Line
.find(DataType
.TAB_COMMA_SPLIT
) == 0:
489 if Line
.find('$') > -1:
490 if Line
.find('$(') < 0 or Line
.find(')') < 0:
491 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
495 if Line
.find('[') > -1 or Line
.find(']') > -1:
497 # Only get one '[' or one ']'
499 if not (Line
.find('[') > -1 and Line
.find(']') > -1):
500 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
502 # Regenerate FileContent
504 NewFileContent
= NewFileContent
+ Line
+ '\r\n'
507 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
509 return NewFileContent
513 # Check if the Filename is including ExtName
514 # Return True if it exists
515 # Raise a error message if it not exists
517 # @param CheckFilename: Name of the file to be checked
518 # @param ExtName: Ext name of the file to be checked
519 # @param ContainerFilename: The container file which describes the file to be
520 # checked, used for error report
521 # @param SectionName: Used for error report
522 # @param Line: The line in container file which defines the file
525 def CheckFileType(CheckFilename
, ExtName
, ContainerFilename
, SectionName
, Line
, LineNo
= -1):
526 if CheckFilename
!= '' and CheckFilename
is not None:
527 (Root
, Ext
) = os
.path
.splitext(CheckFilename
)
528 if Ext
.upper() != ExtName
.upper() and Root
:
529 ContainerFile
= open(ContainerFilename
, 'r').read()
531 LineNo
= GetLineNo(ContainerFile
, Line
)
532 ErrorMsg
= ST
.ERR_SECTIONNAME_INVALID
% (SectionName
, CheckFilename
, ExtName
)
533 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
, Line
=LineNo
, \
534 File
=ContainerFilename
, RaiseError
=Logger
.IS_RAISE_ERROR
)
540 # Check if the file exists
541 # Return True if it exists
542 # Raise a error message if it not exists
544 # @param CheckFilename: Name of the file to be checked
545 # @param WorkspaceDir: Current workspace dir
546 # @param ContainerFilename: The container file which describes the file to
547 # be checked, used for error report
548 # @param SectionName: Used for error report
549 # @param Line: The line in container file which defines the
552 def CheckFileExist(WorkspaceDir
, CheckFilename
, ContainerFilename
, SectionName
, Line
, LineNo
= -1):
554 if CheckFilename
!= '' and CheckFilename
is not None:
555 CheckFile
= WorkspaceFile(WorkspaceDir
, CheckFilename
)
556 if not os
.path
.isfile(CheckFile
):
557 ContainerFile
= open(ContainerFilename
, 'r').read()
559 LineNo
= GetLineNo(ContainerFile
, Line
)
560 ErrorMsg
= ST
.ERR_CHECKFILE_NOTFOUND
% (CheckFile
, SectionName
)
561 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
,
562 File
=ContainerFilename
, Line
=LineNo
, RaiseError
=Logger
.IS_RAISE_ERROR
)
567 # Find the index of a line in a file
569 # @param FileContent: Search scope
570 # @param Line: Search key
572 def GetLineNo(FileContent
, Line
, IsIgnoreComment
=True):
573 LineList
= FileContent
.splitlines()
574 for Index
in range(len(LineList
)):
575 if LineList
[Index
].find(Line
) > -1:
577 # Ignore statement in comment
580 if LineList
[Index
].strip()[0] == DataType
.TAB_COMMENT_SPLIT
:
588 # Raise a parser error
590 # @param Line: String which has error
591 # @param Section: Used for error report
592 # @param File: File which has the string
593 # @param Format: Correct format
595 def RaiseParserError(Line
, Section
, File
, Format
='', LineNo
= -1):
597 LineNo
= GetLineNo(open(os
.path
.normpath(File
), 'r').read(), Line
)
598 ErrorMsg
= ST
.ERR_INVALID_NOTFOUND
% (Line
, Section
)
600 Format
= "Correct format is " + Format
601 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
, File
=File
, Line
=LineNo
, \
602 ExtraData
=Format
, RaiseError
=Logger
.IS_RAISE_ERROR
)
606 # Return a full path with workspace dir
608 # @param WorkspaceDir: Workspace dir
609 # @param Filename: Relative file name
611 def WorkspaceFile(WorkspaceDir
, Filename
):
612 return os
.path
.join(NormPath(WorkspaceDir
), NormPath(Filename
))
616 # Remove '"' which startswith and endswith string
618 # @param String: The string need to be split
620 def SplitString(String
):
621 if String
.startswith('\"'):
623 if String
.endswith('\"'):
627 ## Convert To Sql String
629 # Replace "'" with "''" in each item of StringList
631 # @param StringList: A list for strings to be converted
633 def ConvertToSqlString(StringList
):
634 return list(map(lambda s
: s
.replace("'", "''"), StringList
))
636 ## Convert To Sql String
638 # Replace "'" with "''" in the String
640 # @param String: A String to be converted
642 def ConvertToSqlString2(String
):
643 return String
.replace("'", "''")
647 # Get String of a List
649 # @param Lines: string list
650 # @param Split: split character
652 def GetStringOfList(List
, Split
=' '):
653 if not isinstance(List
, type([])):
657 Str
= Str
+ Item
+ Split
662 # Get HelpTextList from HelpTextClassList
664 # @param HelpTextClassList: Help Text Class List
666 def GetHelpTextList(HelpTextClassList
):
668 if HelpTextClassList
:
669 for HelpText
in HelpTextClassList
:
670 if HelpText
.String
.endswith('\n'):
671 HelpText
.String
= HelpText
.String
[0: len(HelpText
.String
) - len('\n')]
672 List
.extend(HelpText
.String
.split('\n'))
675 ## Get String Array Length
677 # Get String Array Length
679 # @param String: the source string
681 def StringArrayLength(String
):
682 if String
.startswith('L"'):
683 return (len(String
) - 3 + 1) * 2
684 elif String
.startswith('"'):
685 return (len(String
) - 2 + 1)
687 return len(String
.split()) + 1
693 # @param OptionString: the option string
694 # @param Which: Which flag
695 # @param Against: Against flag
697 def RemoveDupOption(OptionString
, Which
="/I", Against
=None):
698 OptionList
= OptionString
.split()
702 for Index
in range(len(OptionList
)):
703 Opt
= OptionList
[Index
]
704 if not Opt
.startswith(Which
):
706 if len(Opt
) > len(Which
):
707 Val
= Opt
[len(Which
):]
711 OptionList
[Index
] = ""
713 ValueList
.append(Val
)
714 return " ".join(OptionList
)
716 ## Check if the string is HexDgit
718 # Return true if all characters in the string are digits and there is at
719 # least one character
720 # or valid Hexs (started with 0x, following by hexdigit letters)
722 # @param string: input string
729 if len(Str
) > 2 and Str
.upper().startswith('0X'):
737 ## Check if the string is HexDgit and its integer value within limit of UINT32
739 # Return true if all characters in the string are digits and there is at
740 # least one character
741 # or valid Hexs (started with 0x, following by hexdigit letters)
743 # @param string: input string
745 def IsHexDigitUINT32(Str
):
748 if (Value
<= 0xFFFFFFFF) and (Value
>= 0):
751 if len(Str
) > 2 and Str
.upper().startswith('0X'):
754 if (Value
<= 0xFFFFFFFF) and (Value
>= 0):
762 # The ASCII text files of type INF, DEC, INI are edited by developers,
763 # and may contain characters that cannot be directly translated to strings that
764 # are conformant with the UDP XML Schema. Any characters in this category
765 # (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF)
766 # must be converted to a space character[0x20] as part of the parsing process.
768 def ConvertSpecialChar(Lines
):
771 ReMatchSpecialChar
= re
.compile(r
"[\x00-\x08]|\x09|\x0b|\x0c|[\x0e-\x1f]|[\x7f-\xff]")
772 RetLines
.append(ReMatchSpecialChar
.sub(' ', line
))
778 # Assume Str is a valid feature flag expression.
779 # Return a list which contains tokens: alpha numeric token and other token
780 # Whitespace are not stripped
782 def __GetTokenList(Str
):
791 if Char
== '"' and PreChar
!= '\\':
792 InQuote
= not InQuote
797 if Token
and Token
!= 'L':
803 InQuote
= not InQuote
807 if not (Char
.isalnum() or Char
in '_'):
818 if PreChar
== '\\' and Char
== '\\':
830 # Convert NE operator to NOT EQ
831 # For example: 1 NE 2 -> 1 NOT EQ 2
833 # @param Expr: Feature flag expression to be converted
835 def ConvertNEToNOTEQ(Expr
):
836 List
= __GetTokenList(Expr
)
837 for Index
in range(len(List
)):
838 if List
[Index
] == 'NE':
839 List
[Index
] = 'NOT EQ'
844 # Convert NOT EQ operator to NE
845 # For example: 1 NOT NE 2 -> 1 NE 2
847 # @param Expr: Feature flag expression to be converted
849 def ConvertNOTEQToNE(Expr
):
850 List
= __GetTokenList(Expr
)
854 if HasNOT
and Token
== 'EQ':
855 # At least, 'NOT' is in the list
856 while not RetList
[-1].strip():
865 RetList
.append(Token
)
867 return ''.join(RetList
)
871 # Split an PCD entry string to Token.CName and PCD value and FFE.
872 # NOTE: PCD Value and FFE can contain "|" in it's expression. And in INF specification, have below rule.
873 # When using the characters "|" or "||" in an expression, the expression must be encapsulated in
874 # open "(" and close ")" parenthesis.
876 # @param String An PCD entry string need to be split.
878 # @return List [PcdTokenCName, Value, FFE]
880 def SplitPcdEntry(String
):
882 return ['', '', ''], False
886 PcdFeatureFlagExp
= ''
888 ValueList
= GetSplitValueList(String
, "|", 1)
891 # Only contain TokenCName
893 if len(ValueList
) == 1:
894 return [ValueList
[0]], True
898 if len(ValueList
) == 2:
899 PcdTokenCName
= ValueList
[0]
902 InParenthesis
= False
904 for StrCh
in ValueList
[1]:
906 InQuote
= not InQuote
907 elif StrCh
== '(' or StrCh
== ')':
908 InParenthesis
= not InParenthesis
911 if not InQuote
or not InParenthesis
:
912 NewValueList
.append(StrItem
.strip())
918 NewValueList
.append(StrItem
.strip())
920 if len(NewValueList
) == 1:
921 PcdValue
= NewValueList
[0]
922 return [PcdTokenCName
, PcdValue
], True
923 elif len(NewValueList
) == 2:
924 PcdValue
= NewValueList
[0]
925 PcdFeatureFlagExp
= NewValueList
[1]
926 return [PcdTokenCName
, PcdValue
, PcdFeatureFlagExp
], True
928 return ['', '', ''], False
930 return ['', '', ''], False
932 ## Check if two arches matched?
937 def IsMatchArch(Arch1
, Arch2
):
938 if 'COMMON' in Arch1
or 'COMMON' in Arch2
:
941 if isinstance(Arch1
, list) and isinstance(Arch2
, list):
947 elif isinstance(Arch1
, list):
948 return Arch2
in Arch1
950 elif isinstance(Arch2
, list):
951 return Arch1
in Arch2
959 # Search all files in FilePath to find the FileName with the largest index
960 # Return the FileName with index +1 under the FilePath
962 def GetUniFileName(FilePath
, FileName
):
965 Files
= os
.listdir(FilePath
)
972 if File
.upper().startswith(FileName
.upper()) and File
.upper().endswith('.UNI'):
973 Index
= File
.upper().replace(FileName
.upper(), '').replace('.UNI', '')
980 IndexNotFound
= False
982 if Index
> LargestIndex
:
983 LargestIndex
= Index
+ 1
985 if LargestIndex
> -1 and not IndexNotFound
:
986 return os
.path
.normpath(os
.path
.join(FilePath
, FileName
+ str(LargestIndex
) + '.uni'))
988 return os
.path
.normpath(os
.path
.join(FilePath
, FileName
+ '.uni'))