]>
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 splited 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: Supportted 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 DFEINE 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 # Revmove '"' which startswith and endswith string
618 # @param String: The string need to be splited
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 isinstance(String
, unicode):
683 return (len(String
) + 1) * 2 + 1
684 elif String
.startswith('L"'):
685 return (len(String
) - 3 + 1) * 2
686 elif String
.startswith('"'):
687 return (len(String
) - 2 + 1)
689 return len(String
.split()) + 1
695 # @param OptionString: the option string
696 # @param Which: Which flag
697 # @param Against: Against flag
699 def RemoveDupOption(OptionString
, Which
="/I", Against
=None):
700 OptionList
= OptionString
.split()
704 for Index
in range(len(OptionList
)):
705 Opt
= OptionList
[Index
]
706 if not Opt
.startswith(Which
):
708 if len(Opt
) > len(Which
):
709 Val
= Opt
[len(Which
):]
713 OptionList
[Index
] = ""
715 ValueList
.append(Val
)
716 return " ".join(OptionList
)
718 ## Check if the string is HexDgit
720 # Return true if all characters in the string are digits and there is at
721 # least one character
722 # or valid Hexs (started with 0x, following by hexdigit letters)
724 # @param string: input string
731 if len(Str
) > 2 and Str
.upper().startswith('0X'):
739 ## Check if the string is HexDgit and its interger value within limit of UINT32
741 # Return true if all characters in the string are digits and there is at
742 # least one character
743 # or valid Hexs (started with 0x, following by hexdigit letters)
745 # @param string: input string
747 def IsHexDigitUINT32(Str
):
750 if (Value
<= 0xFFFFFFFF) and (Value
>= 0):
753 if len(Str
) > 2 and Str
.upper().startswith('0X'):
756 if (Value
<= 0xFFFFFFFF) and (Value
>= 0):
764 # The ASCII text files of type INF, DEC, INI are edited by developers,
765 # and may contain characters that cannot be directly translated to strings that
766 # are conformant with the UDP XML Schema. Any characters in this category
767 # (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF)
768 # must be converted to a space character[0x20] as part of the parsing process.
770 def ConvertSpecialChar(Lines
):
773 ReMatchSpecialChar
= re
.compile(r
"[\x00-\x08]|\x09|\x0b|\x0c|[\x0e-\x1f]|[\x7f-\xff]")
774 RetLines
.append(ReMatchSpecialChar
.sub(' ', line
))
780 # Assume Str is a valid feature flag expression.
781 # Return a list which contains tokens: alpha numeric token and other token
782 # Whitespace are not stripped
784 def __GetTokenList(Str
):
793 if Char
== '"' and PreChar
!= '\\':
794 InQuote
= not InQuote
799 if Token
and Token
!= 'L':
805 InQuote
= not InQuote
809 if not (Char
.isalnum() or Char
in '_'):
820 if PreChar
== '\\' and Char
== '\\':
832 # Convert NE operator to NOT EQ
833 # For example: 1 NE 2 -> 1 NOT EQ 2
835 # @param Expr: Feature flag expression to be converted
837 def ConvertNEToNOTEQ(Expr
):
838 List
= __GetTokenList(Expr
)
839 for Index
in range(len(List
)):
840 if List
[Index
] == 'NE':
841 List
[Index
] = 'NOT EQ'
846 # Convert NOT EQ operator to NE
847 # For example: 1 NOT NE 2 -> 1 NE 2
849 # @param Expr: Feature flag expression to be converted
851 def ConvertNOTEQToNE(Expr
):
852 List
= __GetTokenList(Expr
)
856 if HasNOT
and Token
== 'EQ':
857 # At least, 'NOT' is in the list
858 while not RetList
[-1].strip():
867 RetList
.append(Token
)
869 return ''.join(RetList
)
873 # Split an PCD entry string to Token.CName and PCD value and FFE.
874 # NOTE: PCD Value and FFE can contain "|" in it's expression. And in INF specification, have below rule.
875 # When using the characters "|" or "||" in an expression, the expression must be encapsulated in
876 # open "(" and close ")" parenthesis.
878 # @param String An PCD entry string need to be split.
880 # @return List [PcdTokenCName, Value, FFE]
882 def SplitPcdEntry(String
):
884 return ['', '', ''], False
888 PcdFeatureFlagExp
= ''
890 ValueList
= GetSplitValueList(String
, "|", 1)
893 # Only contain TokenCName
895 if len(ValueList
) == 1:
896 return [ValueList
[0]], True
900 if len(ValueList
) == 2:
901 PcdTokenCName
= ValueList
[0]
904 InParenthesis
= False
906 for StrCh
in ValueList
[1]:
908 InQuote
= not InQuote
909 elif StrCh
== '(' or StrCh
== ')':
910 InParenthesis
= not InParenthesis
913 if not InQuote
or not InParenthesis
:
914 NewValueList
.append(StrItem
.strip())
920 NewValueList
.append(StrItem
.strip())
922 if len(NewValueList
) == 1:
923 PcdValue
= NewValueList
[0]
924 return [PcdTokenCName
, PcdValue
], True
925 elif len(NewValueList
) == 2:
926 PcdValue
= NewValueList
[0]
927 PcdFeatureFlagExp
= NewValueList
[1]
928 return [PcdTokenCName
, PcdValue
, PcdFeatureFlagExp
], True
930 return ['', '', ''], False
932 return ['', '', ''], False
934 ## Check if two arches matched?
939 def IsMatchArch(Arch1
, Arch2
):
940 if 'COMMON' in Arch1
or 'COMMON' in Arch2
:
943 if isinstance(Arch1
, list) and isinstance(Arch2
, list):
949 elif isinstance(Arch1
, list):
950 return Arch2
in Arch1
952 elif isinstance(Arch2
, list):
953 return Arch1
in Arch2
961 # Search all files in FilePath to find the FileName with the largest index
962 # Return the FileName with index +1 under the FilePath
964 def GetUniFileName(FilePath
, FileName
):
967 Files
= os
.listdir(FilePath
)
974 if File
.upper().startswith(FileName
.upper()) and File
.upper().endswith('.UNI'):
975 Index
= File
.upper().replace(FileName
.upper(), '').replace('.UNI', '')
982 IndexNotFound
= False
984 if Index
> LargestIndex
:
985 LargestIndex
= Index
+ 1
987 if LargestIndex
> -1 and not IndexNotFound
:
988 return os
.path
.normpath(os
.path
.join(FilePath
, FileName
+ str(LargestIndex
) + '.uni'))
990 return os
.path
.normpath(os
.path
.join(FilePath
, FileName
+ '.uni'))