]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Library/String.py
b79891ea1417452d40c666f582a4bfbea523c179
2 # This file is used to define common string related functions used in parsing
5 # Copyright (c) 2011 - 2016, 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 from string
import strip
24 import Logger
.Log
as Logger
25 import Library
.DataType
as DataType
26 from Logger
.ToolError
import FORMAT_INVALID
27 from Logger
.ToolError
import PARSER_ERROR
28 from Logger
import StringTable
as ST
31 # Regular expression for matching macro used in DSC/DEC/INF file inclusion
33 gMACRO_PATTERN
= re
.compile("\$\(([_A-Z][_A-Z0-9]*)\)", re
.UNICODE
)
37 # Get a value list from a string with multiple values splited with SplitTag
38 # The default SplitTag is DataType.TAB_VALUE_SPLIT
39 # 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']
41 # @param String: The input string to be splitted
42 # @param SplitTag: The split key, default is DataType.TAB_VALUE_SPLIT
43 # @param MaxSplit: The max number of split values, default is -1
46 def GetSplitValueList(String
, SplitTag
=DataType
.TAB_VALUE_SPLIT
, MaxSplit
= -1):
47 return map(lambda l
: l
.strip(), String
.split(SplitTag
, MaxSplit
))
51 # Find a key's all arches in dict, add the new arch to the list
52 # If not exist any arch, set the arch directly
54 # @param Dict: The input value for Dict
55 # @param Key: The input value for Key
56 # @param Arch: The Arch to be added or merged
58 def MergeArches(Dict
, Key
, Arch
):
59 if Key
in Dict
.keys():
60 Dict
[Key
].append(Arch
)
62 Dict
[Key
] = Arch
.split()
66 # Parse a string with format "DEFINE <VarName> = <PATH>"
67 # Generate a map Defines[VarName] = PATH
68 # Return False if invalid format
70 # @param String: String with DEFINE statement
71 # @param Arch: Supportted Arch
72 # @param Defines: DEFINE statement to be parsed
74 def GenDefines(String
, Arch
, Defines
):
75 if String
.find(DataType
.TAB_DEFINE
+ ' ') > -1:
76 List
= String
.replace(DataType
.TAB_DEFINE
+ ' ', '').\
77 split(DataType
.TAB_EQUAL_SPLIT
)
79 Defines
[(CleanString(List
[0]), Arch
)] = CleanString(List
[1])
85 ## GetLibraryClassesWithModuleType
87 # Get Library Class definition when no module type defined
89 # @param Lines: The content to be parsed
90 # @param Key: Reserved
91 # @param KeyValues: To store data after parsing
92 # @param CommentCharacter: Comment char, used to ignore comment content
94 def GetLibraryClassesWithModuleType(Lines
, Key
, KeyValues
, CommentCharacter
):
95 NewKey
= SplitModuleType(Key
)
96 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
97 LineList
= Lines
.splitlines()
99 Line
= CleanString(Line
, CommentCharacter
)
100 if Line
!= '' and Line
[0] != CommentCharacter
:
101 KeyValues
.append([CleanString(Line
, CommentCharacter
), NewKey
[1]])
109 # @param Lines: The content to be parsed
110 # @param Key: Reserved
111 # @param KeyValues: To store data after parsing
112 # @param CommentCharacter: Comment char, used to ignore comment content
114 def GetDynamics(Lines
, Key
, KeyValues
, CommentCharacter
):
116 # Get SkuId Name List
118 SkuIdNameList
= SplitModuleType(Key
)
120 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
121 LineList
= Lines
.splitlines()
122 for Line
in LineList
:
123 Line
= CleanString(Line
, CommentCharacter
)
124 if Line
!= '' and Line
[0] != CommentCharacter
:
125 KeyValues
.append([CleanString(Line
, CommentCharacter
), SkuIdNameList
[1]])
131 # Split ModuleType out of section defien to get key
132 # [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [
133 # 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]
135 # @param Key: String to be parsed
137 def SplitModuleType(Key
):
138 KeyList
= Key
.split(DataType
.TAB_SPLIT
)
144 # Fill in for moduletype
148 KeyValue
= KeyList
[0]
150 KeyValue
= KeyValue
+ DataType
.TAB_SPLIT
+ KeyList
[1]
151 ReturnValue
.append(KeyValue
)
152 ReturnValue
.append(GetSplitValueList(KeyList
[2]))
156 ## Replace macro in string
158 # This method replace macros used in given string. The macros are given in a
161 # @param String String to be processed
162 # @param MacroDefinitions The macro definitions in the form of dictionary
163 # @param SelfReplacement To decide whether replace un-defined macro to ''
164 # @param Line: The content contain line string and line number
165 # @param FileName: The meta-file file name
167 def ReplaceMacro(String
, MacroDefinitions
=None, SelfReplacement
=False, Line
=None, FileName
=None, Flag
=False):
169 if MacroDefinitions
is None:
170 MacroDefinitions
= {}
171 while MacroDefinitions
:
172 QuotedStringList
= []
173 HaveQuotedMacroFlag
= False
175 MacroUsed
= gMACRO_PATTERN
.findall(String
)
177 ReQuotedString
= re
.compile('\"')
178 QuotedStringList
= ReQuotedString
.split(String
)
179 if len(QuotedStringList
) >= 3:
180 HaveQuotedMacroFlag
= True
183 for QuotedStringItem
in QuotedStringList
:
186 MacroString
+= QuotedStringItem
188 if Count
== len(QuotedStringList
) and Count
% 2 == 0:
189 MacroString
+= QuotedStringItem
191 MacroUsed
= gMACRO_PATTERN
.findall(MacroString
)
193 # no macro found in String, stop replacing
195 if len(MacroUsed
) == 0:
197 for Macro
in MacroUsed
:
198 if Macro
not in MacroDefinitions
:
200 String
= String
.replace("$(%s)" % Macro
, '')
201 Logger
.Debug(5, "Delete undefined MACROs in file %s line %d: %s!" % (FileName
, Line
[1], Line
[0]))
203 if not HaveQuotedMacroFlag
:
204 String
= String
.replace("$(%s)" % Macro
, MacroDefinitions
[Macro
])
207 for QuotedStringItem
in QuotedStringList
:
210 QuotedStringList
[Count
- 1] = QuotedStringList
[Count
- 1].replace("$(%s)" % Macro
,
211 MacroDefinitions
[Macro
])
212 elif Count
== len(QuotedStringList
) and Count
% 2 == 0:
213 QuotedStringList
[Count
- 1] = QuotedStringList
[Count
- 1].replace("$(%s)" % Macro
,
214 MacroDefinitions
[Macro
])
217 if HaveQuotedMacroFlag
:
219 for QuotedStringItem
in QuotedStringList
:
221 if Count
!= len(QuotedStringList
):
222 RetString
+= QuotedStringList
[Count
- 1] + "\""
224 RetString
+= QuotedStringList
[Count
- 1]
229 # in case there's macro not defined
231 if String
== LastString
:
239 # Create a normal path
240 # And replace DFEINE in the path
242 # @param Path: The input value for Path to be converted
243 # @param Defines: A set for DEFINE statement
245 def NormPath(Path
, Defines
=None):
246 IsRelativePath
= False
251 IsRelativePath
= True
253 # Replace with Define
256 Path
= ReplaceMacro(Path
, Defines
)
258 # To local path format
260 Path
= os
.path
.normpath(Path
)
262 if IsRelativePath
and Path
[0] != '.':
263 Path
= os
.path
.join('.', Path
)
268 # Remove comments in a string
271 # @param Line: The string to be cleaned
272 # @param CommentCharacter: Comment char, used to ignore comment content,
273 # default is DataType.TAB_COMMENT_SPLIT
275 def CleanString(Line
, CommentCharacter
=DataType
.TAB_COMMENT_SPLIT
, AllowCppStyleComment
=False):
281 # Replace EDK1's comment character
283 if AllowCppStyleComment
:
284 Line
= Line
.replace(DataType
.TAB_COMMENT_EDK1_SPLIT
, CommentCharacter
)
286 # remove comments, but we should escape comment character in string
289 for Index
in range(0, len(Line
)):
290 if Line
[Index
] == '"':
291 InString
= not InString
292 elif Line
[Index
] == CommentCharacter
and not InString
:
293 Line
= Line
[0: Index
]
296 # remove whitespace again
304 # Split comments in a string
307 # @param Line: The string to be cleaned
308 # @param CommentCharacter: Comment char, used to ignore comment content,
309 # default is DataType.TAB_COMMENT_SPLIT
311 def CleanString2(Line
, CommentCharacter
=DataType
.TAB_COMMENT_SPLIT
, AllowCppStyleComment
=False):
317 # Replace EDK1's comment character
319 if AllowCppStyleComment
:
320 Line
= Line
.replace(DataType
.TAB_COMMENT_EDK1_SPLIT
, CommentCharacter
)
322 # separate comments and statements
324 LineParts
= Line
.split(CommentCharacter
, 1)
326 # remove whitespace again
328 Line
= LineParts
[0].strip()
329 if len(LineParts
) > 1:
330 Comment
= LineParts
[1].strip()
332 # Remove prefixed and trailing comment characters
336 while Start
< End
and Comment
.startswith(CommentCharacter
, Start
, End
):
338 while End
>= 0 and Comment
.endswith(CommentCharacter
, Start
, End
):
340 Comment
= Comment
[Start
:End
]
341 Comment
= Comment
.strip()
347 ## GetMultipleValuesOfKeyFromLines
349 # Parse multiple strings to clean comment and spaces
350 # The result is saved to KeyValues
352 # @param Lines: The content to be parsed
353 # @param Key: Reserved
354 # @param KeyValues: To store data after parsing
355 # @param CommentCharacter: Comment char, used to ignore comment content
357 def GetMultipleValuesOfKeyFromLines(Lines
, Key
, KeyValues
, CommentCharacter
):
362 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
363 LineList
= Lines
.split('\n')
364 for Line
in LineList
:
365 Line
= CleanString(Line
, CommentCharacter
)
366 if Line
!= '' and Line
[0] != CommentCharacter
:
372 # Parse a DEFINE statement to get defined value
375 # @param String: The content to be parsed
376 # @param Key: The key of DEFINE statement
377 # @param CommentCharacter: Comment char, used to ignore comment content
379 def GetDefineValue(String
, Key
, CommentCharacter
):
382 String
= CleanString(String
)
383 return String
[String
.find(Key
+ ' ') + len(Key
+ ' ') : ]
385 ## GetSingleValueOfKeyFromLines
387 # Parse multiple strings as below to get value of each definition line
390 # The result is saved to Dictionary
392 # @param Lines: The content to be parsed
393 # @param Dictionary: To store data after parsing
394 # @param CommentCharacter: Comment char, be used to ignore comment content
395 # @param KeySplitCharacter: Key split char, between key name and key value.
396 # Key1 = Value1, '=' is the key split char
397 # @param ValueSplitFlag: Value split flag, be used to decide if has
399 # @param ValueSplitCharacter: Value split char, be used to split multiple
400 # values. Key1 = Value1|Value2, '|' is the value
403 def GetSingleValueOfKeyFromLines(Lines
, Dictionary
, CommentCharacter
, KeySplitCharacter
, \
404 ValueSplitFlag
, ValueSplitCharacter
):
405 Lines
= Lines
.split('\n')
413 # Handle DEFINE and SPEC
415 if Line
.find(DataType
.TAB_INF_DEFINES_DEFINE
+ ' ') > -1:
416 if '' in DefineValues
:
417 DefineValues
.remove('')
418 DefineValues
.append(GetDefineValue(Line
, DataType
.TAB_INF_DEFINES_DEFINE
, CommentCharacter
))
420 if Line
.find(DataType
.TAB_INF_DEFINES_SPEC
+ ' ') > -1:
422 SpecValues
.remove('')
423 SpecValues
.append(GetDefineValue(Line
, DataType
.TAB_INF_DEFINES_SPEC
, CommentCharacter
))
429 LineList
= Line
.split(KeySplitCharacter
, 1)
430 if len(LineList
) >= 2:
431 Key
= LineList
[0].split()
432 if len(Key
) == 1 and Key
[0][0] != CommentCharacter
:
434 # Remove comments and white spaces
436 LineList
[1] = CleanString(LineList
[1], CommentCharacter
)
438 Value
= map(strip
, LineList
[1].split(ValueSplitCharacter
))
440 Value
= CleanString(LineList
[1], CommentCharacter
).splitlines()
442 if Key
[0] in Dictionary
:
443 if Key
[0] not in Keys
:
444 Dictionary
[Key
[0]] = Value
447 Dictionary
[Key
[0]].extend(Value
)
449 Dictionary
[DataType
.TAB_INF_DEFINES_MACRO
][Key
[0]] = Value
[0]
451 if DefineValues
== []:
455 Dictionary
[DataType
.TAB_INF_DEFINES_DEFINE
] = DefineValues
456 Dictionary
[DataType
.TAB_INF_DEFINES_SPEC
] = SpecValues
460 ## The content to be parsed
462 # Do pre-check for a file before it is parsed
466 # @param FileName: Used for error report
467 # @param FileContent: File content to be parsed
468 # @param SupSectionTag: Used for error report
470 def PreCheck(FileName
, FileContent
, SupSectionTag
):
476 for Line
in FileContent
.splitlines():
481 Line
= CleanString(Line
)
483 # Remove commented line
485 if Line
.find(DataType
.TAB_COMMA_SPLIT
) == 0:
490 if Line
.find('$') > -1:
491 if Line
.find('$(') < 0 or Line
.find(')') < 0:
492 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
496 if Line
.find('[') > -1 or Line
.find(']') > -1:
498 # Only get one '[' or one ']'
500 if not (Line
.find('[') > -1 and Line
.find(']') > -1):
501 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
503 # Regenerate FileContent
505 NewFileContent
= NewFileContent
+ Line
+ '\r\n'
508 Logger
.Error("Parser", FORMAT_INVALID
, Line
=LineNo
, File
=FileName
, RaiseError
=Logger
.IS_RAISE_ERROR
)
510 return NewFileContent
514 # Check if the Filename is including ExtName
515 # Return True if it exists
516 # Raise a error message if it not exists
518 # @param CheckFilename: Name of the file to be checked
519 # @param ExtName: Ext name of the file to be checked
520 # @param ContainerFilename: The container file which describes the file to be
521 # checked, used for error report
522 # @param SectionName: Used for error report
523 # @param Line: The line in container file which defines the file
526 def CheckFileType(CheckFilename
, ExtName
, ContainerFilename
, SectionName
, Line
, LineNo
= -1):
527 if CheckFilename
!= '' and CheckFilename
is not None:
528 (Root
, Ext
) = os
.path
.splitext(CheckFilename
)
529 if Ext
.upper() != ExtName
.upper() and Root
:
530 ContainerFile
= open(ContainerFilename
, 'r').read()
532 LineNo
= GetLineNo(ContainerFile
, Line
)
533 ErrorMsg
= ST
.ERR_SECTIONNAME_INVALID
% (SectionName
, CheckFilename
, ExtName
)
534 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
, Line
=LineNo
, \
535 File
=ContainerFilename
, RaiseError
=Logger
.IS_RAISE_ERROR
)
541 # Check if the file exists
542 # Return True if it exists
543 # Raise a error message if it not exists
545 # @param CheckFilename: Name of the file to be checked
546 # @param WorkspaceDir: Current workspace dir
547 # @param ContainerFilename: The container file which describes the file to
548 # be checked, used for error report
549 # @param SectionName: Used for error report
550 # @param Line: The line in container file which defines the
553 def CheckFileExist(WorkspaceDir
, CheckFilename
, ContainerFilename
, SectionName
, Line
, LineNo
= -1):
555 if CheckFilename
!= '' and CheckFilename
is not None:
556 CheckFile
= WorkspaceFile(WorkspaceDir
, CheckFilename
)
557 if not os
.path
.isfile(CheckFile
):
558 ContainerFile
= open(ContainerFilename
, 'r').read()
560 LineNo
= GetLineNo(ContainerFile
, Line
)
561 ErrorMsg
= ST
.ERR_CHECKFILE_NOTFOUND
% (CheckFile
, SectionName
)
562 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
,
563 File
=ContainerFilename
, Line
=LineNo
, RaiseError
=Logger
.IS_RAISE_ERROR
)
568 # Find the index of a line in a file
570 # @param FileContent: Search scope
571 # @param Line: Search key
573 def GetLineNo(FileContent
, Line
, IsIgnoreComment
=True):
574 LineList
= FileContent
.splitlines()
575 for Index
in range(len(LineList
)):
576 if LineList
[Index
].find(Line
) > -1:
578 # Ignore statement in comment
581 if LineList
[Index
].strip()[0] == DataType
.TAB_COMMENT_SPLIT
:
589 # Raise a parser error
591 # @param Line: String which has error
592 # @param Section: Used for error report
593 # @param File: File which has the string
594 # @param Format: Correct format
596 def RaiseParserError(Line
, Section
, File
, Format
='', LineNo
= -1):
598 LineNo
= GetLineNo(open(os
.path
.normpath(File
), 'r').read(), Line
)
599 ErrorMsg
= ST
.ERR_INVALID_NOTFOUND
% (Line
, Section
)
601 Format
= "Correct format is " + Format
602 Logger
.Error("Parser", PARSER_ERROR
, ErrorMsg
, File
=File
, Line
=LineNo
, \
603 ExtraData
=Format
, RaiseError
=Logger
.IS_RAISE_ERROR
)
607 # Return a full path with workspace dir
609 # @param WorkspaceDir: Workspace dir
610 # @param Filename: Relative file name
612 def WorkspaceFile(WorkspaceDir
, Filename
):
613 return os
.path
.join(NormPath(WorkspaceDir
), NormPath(Filename
))
617 # Revmove '"' which startswith and endswith string
619 # @param String: The string need to be splited
621 def SplitString(String
):
622 if String
.startswith('\"'):
624 if String
.endswith('\"'):
628 ## Convert To Sql String
630 # Replace "'" with "''" in each item of StringList
632 # @param StringList: A list for strings to be converted
634 def ConvertToSqlString(StringList
):
635 return map(lambda s
: s
.replace("'", "''") , StringList
)
637 ## Convert To Sql String
639 # Replace "'" with "''" in the String
641 # @param String: A String to be converted
643 def ConvertToSqlString2(String
):
644 return String
.replace("'", "''")
648 # Get String of a List
650 # @param Lines: string list
651 # @param Split: split character
653 def GetStringOfList(List
, Split
=' '):
654 if type(List
) != type([]):
658 Str
= Str
+ Item
+ Split
663 # Get HelpTextList from HelpTextClassList
665 # @param HelpTextClassList: Help Text Class List
667 def GetHelpTextList(HelpTextClassList
):
669 if HelpTextClassList
:
670 for HelpText
in HelpTextClassList
:
671 if HelpText
.String
.endswith('\n'):
672 HelpText
.String
= HelpText
.String
[0: len(HelpText
.String
) - len('\n')]
673 List
.extend(HelpText
.String
.split('\n'))
676 ## Get String Array Length
678 # Get String Array Length
680 # @param String: the source string
682 def StringArrayLength(String
):
683 if isinstance(String
, unicode):
684 return (len(String
) + 1) * 2 + 1
685 elif String
.startswith('L"'):
686 return (len(String
) - 3 + 1) * 2
687 elif String
.startswith('"'):
688 return (len(String
) - 2 + 1)
690 return len(String
.split()) + 1
696 # @param OptionString: the option string
697 # @param Which: Which flag
698 # @param Against: Against flag
700 def RemoveDupOption(OptionString
, Which
="/I", Against
=None):
701 OptionList
= OptionString
.split()
705 for Index
in range(len(OptionList
)):
706 Opt
= OptionList
[Index
]
707 if not Opt
.startswith(Which
):
709 if len(Opt
) > len(Which
):
710 Val
= Opt
[len(Which
):]
714 OptionList
[Index
] = ""
716 ValueList
.append(Val
)
717 return " ".join(OptionList
)
719 ## Check if the string is HexDgit
721 # Return true if all characters in the string are digits and there is at
722 # least one character
723 # or valid Hexs (started with 0x, following by hexdigit letters)
725 # @param string: input string
732 if len(Str
) > 2 and Str
.upper().startswith('0X'):
740 ## Check if the string is HexDgit and its interger value within limit of UINT32
742 # Return true if all characters in the string are digits and there is at
743 # least one character
744 # or valid Hexs (started with 0x, following by hexdigit letters)
746 # @param string: input string
748 def IsHexDigitUINT32(Str
):
751 if (Value
<= 0xFFFFFFFF) and (Value
>= 0):
754 if len(Str
) > 2 and Str
.upper().startswith('0X'):
757 if (Value
<= 0xFFFFFFFF) and (Value
>= 0):
765 # The ASCII text files of type INF, DEC, INI are edited by developers,
766 # and may contain characters that cannot be directly translated to strings that
767 # are conformant with the UDP XML Schema. Any characters in this category
768 # (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF)
769 # must be converted to a space character[0x20] as part of the parsing process.
771 def ConvertSpecialChar(Lines
):
774 ReMatchSpecialChar
= re
.compile(r
"[\x00-\x08]|\x09|\x0b|\x0c|[\x0e-\x1f]|[\x7f-\xff]")
775 RetLines
.append(ReMatchSpecialChar
.sub(' ', line
))
781 # Assume Str is a valid feature flag expression.
782 # Return a list which contains tokens: alpha numeric token and other token
783 # Whitespace are not stripped
785 def __GetTokenList(Str
):
794 if Char
== '"' and PreChar
!= '\\':
795 InQuote
= not InQuote
800 if Token
and Token
!= 'L':
806 InQuote
= not InQuote
810 if not (Char
.isalnum() or Char
in '_'):
821 if PreChar
== '\\' and Char
== '\\':
833 # Convert NE operator to NOT EQ
834 # For example: 1 NE 2 -> 1 NOT EQ 2
836 # @param Expr: Feature flag expression to be converted
838 def ConvertNEToNOTEQ(Expr
):
839 List
= __GetTokenList(Expr
)
840 for Index
in range(len(List
)):
841 if List
[Index
] == 'NE':
842 List
[Index
] = 'NOT EQ'
847 # Convert NOT EQ operator to NE
848 # For example: 1 NOT NE 2 -> 1 NE 2
850 # @param Expr: Feature flag expression to be converted
852 def ConvertNOTEQToNE(Expr
):
853 List
= __GetTokenList(Expr
)
857 if HasNOT
and Token
== 'EQ':
858 # At least, 'NOT' is in the list
859 while not RetList
[-1].strip():
868 RetList
.append(Token
)
870 return ''.join(RetList
)
874 # Split an PCD entry string to Token.CName and PCD value and FFE.
875 # NOTE: PCD Value and FFE can contain "|" in it's expression. And in INF specification, have below rule.
876 # When using the characters "|" or "||" in an expression, the expression must be encapsulated in
877 # open "(" and close ")" parenthesis.
879 # @param String An PCD entry string need to be split.
881 # @return List [PcdTokenCName, Value, FFE]
883 def SplitPcdEntry(String
):
885 return ['', '', ''], False
889 PcdFeatureFlagExp
= ''
891 ValueList
= GetSplitValueList(String
, "|", 1)
894 # Only contain TokenCName
896 if len(ValueList
) == 1:
897 return [ValueList
[0]], True
901 if len(ValueList
) == 2:
902 PcdTokenCName
= ValueList
[0]
905 InParenthesis
= False
907 for StrCh
in ValueList
[1]:
909 InQuote
= not InQuote
910 elif StrCh
== '(' or StrCh
== ')':
911 InParenthesis
= not InParenthesis
914 if not InQuote
or not InParenthesis
:
915 NewValueList
.append(StrItem
.strip())
921 NewValueList
.append(StrItem
.strip())
923 if len(NewValueList
) == 1:
924 PcdValue
= NewValueList
[0]
925 return [PcdTokenCName
, PcdValue
], True
926 elif len(NewValueList
) == 2:
927 PcdValue
= NewValueList
[0]
928 PcdFeatureFlagExp
= NewValueList
[1]
929 return [PcdTokenCName
, PcdValue
, PcdFeatureFlagExp
], True
931 return ['', '', ''], False
933 return ['', '', ''], False
935 ## Check if two arches matched?
940 def IsMatchArch(Arch1
, Arch2
):
941 if 'COMMON' in Arch1
or 'COMMON' in Arch2
:
943 if isinstance(Arch1
, basestring
) and isinstance(Arch2
, basestring
):
947 if isinstance(Arch1
, basestring
) and isinstance(Arch2
, list):
948 return Arch1
in Arch2
950 if isinstance(Arch2
, basestring
) and isinstance(Arch1
, list):
951 return Arch2
in Arch1
953 if isinstance(Arch1
, list) and isinstance(Arch2
, list):
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'))