]>
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 # SPDX-License-Identifier: BSD-2-Clause-Patent
17 import Logger
.Log
as Logger
18 import Library
.DataType
as DataType
19 from Logger
.ToolError
import FORMAT_INVALID
20 from Logger
.ToolError
import PARSER_ERROR
21 from Logger
import StringTable
as ST
24 # Regular expression for matching macro used in DSC/DEC/INF file inclusion
26 gMACRO_PATTERN
= re
.compile("\$\(([_A-Z][_A-Z0-9]*)\)", re
.UNICODE
)
30 # Get a value list from a string with multiple values split with SplitTag
31 # The default SplitTag is DataType.TAB_VALUE_SPLIT
32 # 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']
34 # @param String: The input string to be splitted
35 # @param SplitTag: The split key, default is DataType.TAB_VALUE_SPLIT
36 # @param MaxSplit: The max number of split values, default is -1
39 def GetSplitValueList(String
, SplitTag
=DataType
.TAB_VALUE_SPLIT
, MaxSplit
= -1):
40 return list(map(lambda l
: l
.strip(), String
.split(SplitTag
, MaxSplit
)))
44 # Find a key's all arches in dict, add the new arch to the list
45 # If not exist any arch, set the arch directly
47 # @param Dict: The input value for Dict
48 # @param Key: The input value for Key
49 # @param Arch: The Arch to be added or merged
51 def MergeArches(Dict
, Key
, Arch
):
52 if Key
in Dict
.keys():
53 Dict
[Key
].append(Arch
)
55 Dict
[Key
] = Arch
.split()
59 # Parse a string with format "DEFINE <VarName> = <PATH>"
60 # Generate a map Defines[VarName] = PATH
61 # Return False if invalid format
63 # @param String: String with DEFINE statement
64 # @param Arch: Supported Arch
65 # @param Defines: DEFINE statement to be parsed
67 def GenDefines(String
, Arch
, Defines
):
68 if String
.find(DataType
.TAB_DEFINE
+ ' ') > -1:
69 List
= String
.replace(DataType
.TAB_DEFINE
+ ' ', '').\
70 split(DataType
.TAB_EQUAL_SPLIT
)
72 Defines
[(CleanString(List
[0]), Arch
)] = CleanString(List
[1])
78 ## GetLibraryClassesWithModuleType
80 # Get Library Class definition when no module type defined
82 # @param Lines: The content to be parsed
83 # @param Key: Reserved
84 # @param KeyValues: To store data after parsing
85 # @param CommentCharacter: Comment char, used to ignore comment content
87 def GetLibraryClassesWithModuleType(Lines
, Key
, KeyValues
, CommentCharacter
):
88 NewKey
= SplitModuleType(Key
)
89 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
90 LineList
= Lines
.splitlines()
92 Line
= CleanString(Line
, CommentCharacter
)
93 if Line
!= '' and Line
[0] != CommentCharacter
:
94 KeyValues
.append([CleanString(Line
, CommentCharacter
), NewKey
[1]])
102 # @param Lines: The content to be parsed
103 # @param Key: Reserved
104 # @param KeyValues: To store data after parsing
105 # @param CommentCharacter: Comment char, used to ignore comment content
107 def GetDynamics(Lines
, Key
, KeyValues
, CommentCharacter
):
109 # Get SkuId Name List
111 SkuIdNameList
= SplitModuleType(Key
)
113 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
114 LineList
= Lines
.splitlines()
115 for Line
in LineList
:
116 Line
= CleanString(Line
, CommentCharacter
)
117 if Line
!= '' and Line
[0] != CommentCharacter
:
118 KeyValues
.append([CleanString(Line
, CommentCharacter
), SkuIdNameList
[1]])
124 # Split ModuleType out of section defien to get key
125 # [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [
126 # 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]
128 # @param Key: String to be parsed
130 def SplitModuleType(Key
):
131 KeyList
= Key
.split(DataType
.TAB_SPLIT
)
137 # Fill in for moduletype
141 KeyValue
= KeyList
[0]
143 KeyValue
= KeyValue
+ DataType
.TAB_SPLIT
+ KeyList
[1]
144 ReturnValue
.append(KeyValue
)
145 ReturnValue
.append(GetSplitValueList(KeyList
[2]))
149 ## Replace macro in string
151 # This method replace macros used in given string. The macros are given in a
154 # @param String String to be processed
155 # @param MacroDefinitions The macro definitions in the form of dictionary
156 # @param SelfReplacement To decide whether replace un-defined macro to ''
157 # @param Line: The content contain line string and line number
158 # @param FileName: The meta-file file name
160 def ReplaceMacro(String
, MacroDefinitions
=None, SelfReplacement
=False, Line
=None, FileName
=None, Flag
=False):
162 if MacroDefinitions
is None:
163 MacroDefinitions
= {}
164 while MacroDefinitions
:
165 QuotedStringList
= []
166 HaveQuotedMacroFlag
= False
168 MacroUsed
= gMACRO_PATTERN
.findall(String
)
170 ReQuotedString
= re
.compile('\"')
171 QuotedStringList
= ReQuotedString
.split(String
)
172 if len(QuotedStringList
) >= 3:
173 HaveQuotedMacroFlag
= True
176 for QuotedStringItem
in QuotedStringList
:
179 MacroString
+= QuotedStringItem
181 if Count
== len(QuotedStringList
) and Count
% 2 == 0:
182 MacroString
+= QuotedStringItem
184 MacroUsed
= gMACRO_PATTERN
.findall(MacroString
)
186 # no macro found in String, stop replacing
188 if len(MacroUsed
) == 0:
190 for Macro
in MacroUsed
:
191 if Macro
not in MacroDefinitions
:
193 String
= String
.replace("$(%s)" % Macro
, '')
194 Logger
.Debug(5, "Delete undefined MACROs in file %s line %d: %s!" % (FileName
, Line
[1], Line
[0]))
196 if not HaveQuotedMacroFlag
:
197 String
= String
.replace("$(%s)" % Macro
, MacroDefinitions
[Macro
])
200 for QuotedStringItem
in QuotedStringList
:
203 QuotedStringList
[Count
- 1] = QuotedStringList
[Count
- 1].replace("$(%s)" % Macro
,
204 MacroDefinitions
[Macro
])
205 elif Count
== len(QuotedStringList
) and Count
% 2 == 0:
206 QuotedStringList
[Count
- 1] = QuotedStringList
[Count
- 1].replace("$(%s)" % Macro
,
207 MacroDefinitions
[Macro
])
210 if HaveQuotedMacroFlag
:
212 for QuotedStringItem
in QuotedStringList
:
214 if Count
!= len(QuotedStringList
):
215 RetString
+= QuotedStringList
[Count
- 1] + "\""
217 RetString
+= QuotedStringList
[Count
- 1]
222 # in case there's macro not defined
224 if String
== LastString
:
232 # Create a normal path
233 # And replace DEFINE in the path
235 # @param Path: The input value for Path to be converted
236 # @param Defines: A set for DEFINE statement
238 def NormPath(Path
, Defines
=None):
239 IsRelativePath
= False
244 IsRelativePath
= True
246 # Replace with Define
249 Path
= ReplaceMacro(Path
, Defines
)
251 # To local path format
253 Path
= os
.path
.normpath(Path
)
255 if IsRelativePath
and Path
[0] != '.':
256 Path
= os
.path
.join('.', Path
)
261 # Remove comments in a string
264 # @param Line: The string to be cleaned
265 # @param CommentCharacter: Comment char, used to ignore comment content,
266 # default is DataType.TAB_COMMENT_SPLIT
268 def CleanString(Line
, CommentCharacter
=DataType
.TAB_COMMENT_SPLIT
, AllowCppStyleComment
=False):
274 # Replace EDK1's comment character
276 if AllowCppStyleComment
:
277 Line
= Line
.replace(DataType
.TAB_COMMENT_EDK1_SPLIT
, CommentCharacter
)
279 # remove comments, but we should escape comment character in string
282 for Index
in range(0, len(Line
)):
283 if Line
[Index
] == '"':
284 InString
= not InString
285 elif Line
[Index
] == CommentCharacter
and not InString
:
286 Line
= Line
[0: Index
]
289 # remove whitespace again
297 # Split comments in a string
300 # @param Line: The string to be cleaned
301 # @param CommentCharacter: Comment char, used to ignore comment content,
302 # default is DataType.TAB_COMMENT_SPLIT
304 def CleanString2(Line
, CommentCharacter
=DataType
.TAB_COMMENT_SPLIT
, AllowCppStyleComment
=False):
310 # Replace EDK1's comment character
312 if AllowCppStyleComment
:
313 Line
= Line
.replace(DataType
.TAB_COMMENT_EDK1_SPLIT
, CommentCharacter
)
315 # separate comments and statements
317 LineParts
= Line
.split(CommentCharacter
, 1)
319 # remove whitespace again
321 Line
= LineParts
[0].strip()
322 if len(LineParts
) > 1:
323 Comment
= LineParts
[1].strip()
325 # Remove prefixed and trailing comment characters
329 while Start
< End
and Comment
.startswith(CommentCharacter
, Start
, End
):
331 while End
>= 0 and Comment
.endswith(CommentCharacter
, Start
, End
):
333 Comment
= Comment
[Start
:End
]
334 Comment
= Comment
.strip()
340 ## GetMultipleValuesOfKeyFromLines
342 # Parse multiple strings to clean comment and spaces
343 # The result is saved to KeyValues
345 # @param Lines: The content to be parsed
346 # @param Key: Reserved
347 # @param KeyValues: To store data after parsing
348 # @param CommentCharacter: Comment char, used to ignore comment content
350 def GetMultipleValuesOfKeyFromLines(Lines
, Key
, KeyValues
, CommentCharacter
):
355 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
356 LineList
= Lines
.split('\n')
357 for Line
in LineList
:
358 Line
= CleanString(Line
, CommentCharacter
)
359 if Line
!= '' and Line
[0] != CommentCharacter
:
365 # Parse a DEFINE statement to get defined value
368 # @param String: The content to be parsed
369 # @param Key: The key of DEFINE statement
370 # @param CommentCharacter: Comment char, used to ignore comment content
372 def GetDefineValue(String
, Key
, CommentCharacter
):
375 String
= CleanString(String
)
376 return String
[String
.find(Key
+ ' ') + len(Key
+ ' ') : ]
378 ## GetSingleValueOfKeyFromLines
380 # Parse multiple strings as below to get value of each definition line
383 # The result is saved to Dictionary
385 # @param Lines: The content to be parsed
386 # @param Dictionary: To store data after parsing
387 # @param CommentCharacter: Comment char, be used to ignore comment content
388 # @param KeySplitCharacter: Key split char, between key name and key value.
389 # Key1 = Value1, '=' is the key split char
390 # @param ValueSplitFlag: Value split flag, be used to decide if has
392 # @param ValueSplitCharacter: Value split char, be used to split multiple
393 # values. Key1 = Value1|Value2, '|' is the value
396 def GetSingleValueOfKeyFromLines(Lines
, Dictionary
, CommentCharacter
, KeySplitCharacter
, \
397 ValueSplitFlag
, ValueSplitCharacter
):
398 Lines
= Lines
.split('\n')
406 # Handle DEFINE and SPEC
408 if Line
.find(DataType
.TAB_INF_DEFINES_DEFINE
+ ' ') > -1:
409 if '' in DefineValues
:
410 DefineValues
.remove('')
411 DefineValues
.append(GetDefineValue(Line
, DataType
.TAB_INF_DEFINES_DEFINE
, CommentCharacter
))
413 if Line
.find(DataType
.TAB_INF_DEFINES_SPEC
+ ' ') > -1:
415 SpecValues
.remove('')
416 SpecValues
.append(GetDefineValue(Line
, DataType
.TAB_INF_DEFINES_SPEC
, CommentCharacter
))
422 LineList
= Line
.split(KeySplitCharacter
, 1)
423 if len(LineList
) >= 2:
424 Key
= LineList
[0].split()
425 if len(Key
) == 1 and Key
[0][0] != CommentCharacter
:
427 # Remove comments and white spaces
429 LineList
[1] = CleanString(LineList
[1], CommentCharacter
)
431 Value
= list(map(lambda x
: x
.strip(), LineList
[1].split(ValueSplitCharacter
)))
433 Value
= CleanString(LineList
[1], CommentCharacter
).splitlines()
435 if Key
[0] in Dictionary
:
436 if Key
[0] not in Keys
:
437 Dictionary
[Key
[0]] = Value
440 Dictionary
[Key
[0]].extend(Value
)
442 Dictionary
[DataType
.TAB_INF_DEFINES_MACRO
][Key
[0]] = Value
[0]
444 if DefineValues
== []:
448 Dictionary
[DataType
.TAB_INF_DEFINES_DEFINE
] = DefineValues
449 Dictionary
[DataType
.TAB_INF_DEFINES_SPEC
] = SpecValues
453 ## The content to be parsed
455 # Do pre-check for a file before it is parsed
459 # @param FileName: Used for error report
460 # @param FileContent: File content to be parsed
461 # @param SupSectionTag: Used for error report
463 def PreCheck(FileName
, FileContent
, SupSectionTag
):
469 for Line
in FileContent
.splitlines():
474 Line
= CleanString(Line
)
476 # Remove commented line
478 if Line
.find(DataType
.TAB_COMMA_SPLIT
) == 0:
483 if Line
.find('$') > -1:
484 if Line
.find('$(') < 0 or Line
.find(')') < 0:
485 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
489 if Line
.find('[') > -1 or Line
.find(']') > -1:
491 # Only get one '[' or one ']'
493 if not (Line
.find('[') > -1 and Line
.find(']') > -1):
494 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
496 # Regenerate FileContent
498 NewFileContent
= NewFileContent
+ Line
+ '\r\n'
501 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
503 return NewFileContent
507 # Check if the Filename is including ExtName
508 # Return True if it exists
509 # Raise a error message if it not exists
511 # @param CheckFilename: Name of the file to be checked
512 # @param ExtName: Ext name of the file to be checked
513 # @param ContainerFilename: The container file which describes the file to be
514 # checked, used for error report
515 # @param SectionName: Used for error report
516 # @param Line: The line in container file which defines the file
519 def CheckFileType(CheckFilename
, ExtName
, ContainerFilename
, SectionName
, Line
, LineNo
= -1):
520 if CheckFilename
!= '' and CheckFilename
is not None:
521 (Root
, Ext
) = os
.path
.splitext(CheckFilename
)
522 if Ext
.upper() != ExtName
.upper() and Root
:
523 ContainerFile
= open(ContainerFilename
, 'r').read()
525 LineNo
= GetLineNo(ContainerFile
, Line
)
526 ErrorMsg
= ST
.ERR_SECTIONNAME_INVALID
% (SectionName
, CheckFilename
, ExtName
)
527 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
, Line
=LineNo
, \
528 File
=ContainerFilename
, RaiseError
=Logger
.IS_RAISE_ERROR
)
534 # Check if the file exists
535 # Return True if it exists
536 # Raise a error message if it not exists
538 # @param CheckFilename: Name of the file to be checked
539 # @param WorkspaceDir: Current workspace dir
540 # @param ContainerFilename: The container file which describes the file to
541 # be checked, used for error report
542 # @param SectionName: Used for error report
543 # @param Line: The line in container file which defines the
546 def CheckFileExist(WorkspaceDir
, CheckFilename
, ContainerFilename
, SectionName
, Line
, LineNo
= -1):
548 if CheckFilename
!= '' and CheckFilename
is not None:
549 CheckFile
= WorkspaceFile(WorkspaceDir
, CheckFilename
)
550 if not os
.path
.isfile(CheckFile
):
551 ContainerFile
= open(ContainerFilename
, 'r').read()
553 LineNo
= GetLineNo(ContainerFile
, Line
)
554 ErrorMsg
= ST
.ERR_CHECKFILE_NOTFOUND
% (CheckFile
, SectionName
)
555 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
,
556 File
=ContainerFilename
, Line
=LineNo
, RaiseError
=Logger
.IS_RAISE_ERROR
)
561 # Find the index of a line in a file
563 # @param FileContent: Search scope
564 # @param Line: Search key
566 def GetLineNo(FileContent
, Line
, IsIgnoreComment
=True):
567 LineList
= FileContent
.splitlines()
568 for Index
in range(len(LineList
)):
569 if LineList
[Index
].find(Line
) > -1:
571 # Ignore statement in comment
574 if LineList
[Index
].strip()[0] == DataType
.TAB_COMMENT_SPLIT
:
582 # Raise a parser error
584 # @param Line: String which has error
585 # @param Section: Used for error report
586 # @param File: File which has the string
587 # @param Format: Correct format
589 def RaiseParserError(Line
, Section
, File
, Format
='', LineNo
= -1):
591 LineNo
= GetLineNo(open(os
.path
.normpath(File
), 'r').read(), Line
)
592 ErrorMsg
= ST
.ERR_INVALID_NOTFOUND
% (Line
, Section
)
594 Format
= "Correct format is " + Format
595 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
, File
=File
, Line
=LineNo
, \
596 ExtraData
=Format
, RaiseError
=Logger
.IS_RAISE_ERROR
)
600 # Return a full path with workspace dir
602 # @param WorkspaceDir: Workspace dir
603 # @param Filename: Relative file name
605 def WorkspaceFile(WorkspaceDir
, Filename
):
606 return os
.path
.join(NormPath(WorkspaceDir
), NormPath(Filename
))
610 # Remove '"' which startswith and endswith string
612 # @param String: The string need to be split
614 def SplitString(String
):
615 if String
.startswith('\"'):
617 if String
.endswith('\"'):
621 ## Convert To Sql String
623 # Replace "'" with "''" in each item of StringList
625 # @param StringList: A list for strings to be converted
627 def ConvertToSqlString(StringList
):
628 return list(map(lambda s
: s
.replace("'", "''"), StringList
))
630 ## Convert To Sql String
632 # Replace "'" with "''" in the String
634 # @param String: A String to be converted
636 def ConvertToSqlString2(String
):
637 return String
.replace("'", "''")
641 # Get String of a List
643 # @param Lines: string list
644 # @param Split: split character
646 def GetStringOfList(List
, Split
=' '):
647 if not isinstance(List
, type([])):
651 Str
= Str
+ Item
+ Split
656 # Get HelpTextList from HelpTextClassList
658 # @param HelpTextClassList: Help Text Class List
660 def GetHelpTextList(HelpTextClassList
):
662 if HelpTextClassList
:
663 for HelpText
in HelpTextClassList
:
664 if HelpText
.String
.endswith('\n'):
665 HelpText
.String
= HelpText
.String
[0: len(HelpText
.String
) - len('\n')]
666 List
.extend(HelpText
.String
.split('\n'))
669 ## Get String Array Length
671 # Get String Array Length
673 # @param String: the source string
675 def StringArrayLength(String
):
676 if String
.startswith('L"'):
677 return (len(String
) - 3 + 1) * 2
678 elif String
.startswith('"'):
679 return (len(String
) - 2 + 1)
681 return len(String
.split()) + 1
687 # @param OptionString: the option string
688 # @param Which: Which flag
689 # @param Against: Against flag
691 def RemoveDupOption(OptionString
, Which
="/I", Against
=None):
692 OptionList
= OptionString
.split()
696 for Index
in range(len(OptionList
)):
697 Opt
= OptionList
[Index
]
698 if not Opt
.startswith(Which
):
700 if len(Opt
) > len(Which
):
701 Val
= Opt
[len(Which
):]
705 OptionList
[Index
] = ""
707 ValueList
.append(Val
)
708 return " ".join(OptionList
)
710 ## Check if the string is HexDgit
712 # Return true if all characters in the string are digits and there is at
713 # least one character
714 # or valid Hexs (started with 0x, following by hexdigit letters)
716 # @param string: input string
723 if len(Str
) > 2 and Str
.upper().startswith('0X'):
731 ## Check if the string is HexDgit and its integer value within limit of UINT32
733 # Return true if all characters in the string are digits and there is at
734 # least one character
735 # or valid Hexs (started with 0x, following by hexdigit letters)
737 # @param string: input string
739 def IsHexDigitUINT32(Str
):
742 if (Value
<= 0xFFFFFFFF) and (Value
>= 0):
745 if len(Str
) > 2 and Str
.upper().startswith('0X'):
748 if (Value
<= 0xFFFFFFFF) and (Value
>= 0):
756 # The ASCII text files of type INF, DEC, INI are edited by developers,
757 # and may contain characters that cannot be directly translated to strings that
758 # are conformant with the UDP XML Schema. Any characters in this category
759 # (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF)
760 # must be converted to a space character[0x20] as part of the parsing process.
762 def ConvertSpecialChar(Lines
):
765 ReMatchSpecialChar
= re
.compile(r
"[\x00-\x08]|\x09|\x0b|\x0c|[\x0e-\x1f]|[\x7f-\xff]")
766 RetLines
.append(ReMatchSpecialChar
.sub(' ', line
))
772 # Assume Str is a valid feature flag expression.
773 # Return a list which contains tokens: alpha numeric token and other token
774 # Whitespace are not stripped
776 def __GetTokenList(Str
):
785 if Char
== '"' and PreChar
!= '\\':
786 InQuote
= not InQuote
791 if Token
and Token
!= 'L':
797 InQuote
= not InQuote
801 if not (Char
.isalnum() or Char
in '_'):
812 if PreChar
== '\\' and Char
== '\\':
824 # Convert NE operator to NOT EQ
825 # For example: 1 NE 2 -> 1 NOT EQ 2
827 # @param Expr: Feature flag expression to be converted
829 def ConvertNEToNOTEQ(Expr
):
830 List
= __GetTokenList(Expr
)
831 for Index
in range(len(List
)):
832 if List
[Index
] == 'NE':
833 List
[Index
] = 'NOT EQ'
838 # Convert NOT EQ operator to NE
839 # For example: 1 NOT NE 2 -> 1 NE 2
841 # @param Expr: Feature flag expression to be converted
843 def ConvertNOTEQToNE(Expr
):
844 List
= __GetTokenList(Expr
)
848 if HasNOT
and Token
== 'EQ':
849 # At least, 'NOT' is in the list
850 while not RetList
[-1].strip():
859 RetList
.append(Token
)
861 return ''.join(RetList
)
865 # Split an PCD entry string to Token.CName and PCD value and FFE.
866 # NOTE: PCD Value and FFE can contain "|" in its expression. And in INF specification, have below rule.
867 # When using the characters "|" or "||" in an expression, the expression must be encapsulated in
868 # open "(" and close ")" parenthesis.
870 # @param String An PCD entry string need to be split.
872 # @return List [PcdTokenCName, Value, FFE]
874 def SplitPcdEntry(String
):
876 return ['', '', ''], False
880 PcdFeatureFlagExp
= ''
882 ValueList
= GetSplitValueList(String
, "|", 1)
885 # Only contain TokenCName
887 if len(ValueList
) == 1:
888 return [ValueList
[0]], True
892 if len(ValueList
) == 2:
893 PcdTokenCName
= ValueList
[0]
896 InParenthesis
= False
898 for StrCh
in ValueList
[1]:
900 InQuote
= not InQuote
901 elif StrCh
== '(' or StrCh
== ')':
902 InParenthesis
= not InParenthesis
905 if not InQuote
or not InParenthesis
:
906 NewValueList
.append(StrItem
.strip())
912 NewValueList
.append(StrItem
.strip())
914 if len(NewValueList
) == 1:
915 PcdValue
= NewValueList
[0]
916 return [PcdTokenCName
, PcdValue
], True
917 elif len(NewValueList
) == 2:
918 PcdValue
= NewValueList
[0]
919 PcdFeatureFlagExp
= NewValueList
[1]
920 return [PcdTokenCName
, PcdValue
, PcdFeatureFlagExp
], True
922 return ['', '', ''], False
924 return ['', '', ''], False
926 ## Check if two arches matched?
931 def IsMatchArch(Arch1
, Arch2
):
932 if 'COMMON' in Arch1
or 'COMMON' in Arch2
:
935 if isinstance(Arch1
, list) and isinstance(Arch2
, list):
941 elif isinstance(Arch1
, list):
942 return Arch2
in Arch1
944 elif isinstance(Arch2
, list):
945 return Arch1
in Arch2
953 # Search all files in FilePath to find the FileName with the largest index
954 # Return the FileName with index +1 under the FilePath
956 def GetUniFileName(FilePath
, FileName
):
959 Files
= os
.listdir(FilePath
)
966 if File
.upper().startswith(FileName
.upper()) and File
.upper().endswith('.UNI'):
967 Index
= File
.upper().replace(FileName
.upper(), '').replace('.UNI', '')
974 IndexNotFound
= False
976 if Index
> LargestIndex
:
977 LargestIndex
= Index
+ 1
979 if LargestIndex
> -1 and not IndexNotFound
:
980 return os
.path
.normpath(os
.path
.join(FilePath
, FileName
+ str(LargestIndex
) + '.uni'))
982 return os
.path
.normpath(os
.path
.join(FilePath
, FileName
+ '.uni'))