2 # This file is used to parse and evaluate expression in directive or PCD value.
4 # Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 from Common
.GlobalData
import *
16 from CommonDataClass
.Exceptions
import BadExpression
17 from CommonDataClass
.Exceptions
import WrnExpression
18 from Misc
import GuidStringToGuidStructureString
, ParseFieldValue
19 import Common
.EdkLogger
as EdkLogger
22 ERR_STRING_EXPR
= 'This operator cannot be used in string expression: [%s].'
23 ERR_SNYTAX
= 'Syntax error, the rest of expression cannot be evaluated: [%s].'
24 ERR_MATCH
= 'No matching right parenthesis.'
25 ERR_STRING_TOKEN
= 'Bad string token: [%s].'
26 ERR_MACRO_TOKEN
= 'Bad macro token: [%s].'
27 ERR_EMPTY_TOKEN
= 'Empty token is not allowed.'
28 ERR_PCD_RESOLVE
= 'PCD token cannot be resolved: [%s].'
29 ERR_VALID_TOKEN
= 'No more valid token found from rest of string: [%s].'
30 ERR_EXPR_TYPE
= 'Different types found in expression.'
31 ERR_OPERATOR_UNSUPPORT
= 'Unsupported operator: [%s]'
32 ERR_REL_NOT_IN
= 'Expect "IN" after "not" operator.'
33 WRN_BOOL_EXPR
= 'Operand of boolean type cannot be used in arithmetic expression.'
34 WRN_EQCMP_STR_OTHERS
= '== Comparison between Operand of string type and Boolean/Number Type always return False.'
35 WRN_NECMP_STR_OTHERS
= '!= Comparison between Operand of string type and Boolean/Number Type always return True.'
36 ERR_RELCMP_STR_OTHERS
= 'Operator taking Operand of string type and Boolean/Number Type is not allowed: [%s].'
37 ERR_STRING_CMP
= 'Unicode string and general string cannot be compared: [%s %s %s]'
38 ERR_ARRAY_TOKEN
= 'Bad C array or C format GUID token: [%s].'
39 ERR_ARRAY_ELE
= 'This must be HEX value for NList or Array: [%s].'
40 ERR_EMPTY_EXPR
= 'Empty expression is not allowed.'
41 ERR_IN_OPERAND
= 'Macro after IN operator can only be: $(FAMILY), $(ARCH), $(TOOL_CHAIN_TAG) and $(TARGET).'
44 # Split string to list according double quote
45 # For example: abc"de\"f"ghi"jkl"mn will be: ['abc', '"de\"f"', 'ghi', '"jkl"', 'mn']
47 def SplitString(String
):
48 # There might be escaped quote: "abc\"def\\\"ghi"
49 Str
= String
.replace('\\\\', '//').replace('\\\"', '\\\'')
53 for i
, ch
in enumerate(Str
):
66 raise BadExpression(ERR_STRING_TOKEN
% Item
)
73 def ReplaceExprMacro(String
, Macros
, ExceptionList
= None):
74 StrList
= SplitString(String
)
75 for i
, String
in enumerate(StrList
):
77 if String
.startswith('"'):
79 MacroStartPos
= String
.find('$(')
81 for Pcd
in gPlatformPcds
.keys():
83 if Pcd
not in gConditionalPcds
:
84 gConditionalPcds
.append(Pcd
)
87 while MacroStartPos
>= 0:
88 RetStr
= String
[0:MacroStartPos
]
89 MacroEndPos
= String
.find(')', MacroStartPos
)
91 raise BadExpression(ERR_MACRO_TOKEN
% String
[MacroStartPos
:])
92 Macro
= String
[MacroStartPos
+2:MacroEndPos
]
93 if Macro
not in Macros
:
94 # From C reference manual:
95 # If an undefined macro name appears in the constant-expression of
96 # !if or !elif, it is replaced by the integer constant 0.
99 Tklst
= RetStr
.split()
100 if Tklst
and Tklst
[-1] in ['IN', 'in'] and ExceptionList
and Macro
not in ExceptionList
:
101 raise BadExpression(ERR_IN_OPERAND
)
102 # Make sure the macro in exception list is encapsulated by double quote
103 # For example: DEFINE ARCH = IA32 X64
104 # $(ARCH) is replaced with "IA32 X64"
105 if ExceptionList
and Macro
in ExceptionList
:
106 RetStr
+= '"' + Macros
[Macro
] + '"'
107 elif Macros
[Macro
].strip():
108 RetStr
+= Macros
[Macro
]
112 RetStr
+= Macros
[Macro
]
113 RetStr
+= String
[MacroEndPos
+1:]
115 MacroStartPos
= String
.find('$(')
117 return ''.join(StrList
)
119 # transfer int to string for in/not in expression
123 StrList
.append(chr(Value
& 0xff))
125 Value
= '"' + ''.join(StrList
) + '"'
128 SupportedInMacroList
= ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH', 'FAMILY']
130 class ValueExpression(object):
131 # Logical operator mapping
133 '&&' : 'and', '||' : 'or',
134 '!' : 'not', 'AND': 'and',
135 'OR' : 'or' , 'NOT': 'not',
136 'XOR': '^' , 'xor': '^',
137 'EQ' : '==' , 'NE' : '!=',
138 'GT' : '>' , 'LT' : '<',
139 'GE' : '>=' , 'LE' : '<=',
143 NonLetterOpLst
= ['+', '-', '*', '/', '%', '&', '|', '^', '~', '<<', '>>', '!', '=', '>', '<', '?', ':']
145 PcdPattern
= re
.compile(r
'[_a-zA-Z][0-9A-Za-z_]*\.[_a-zA-Z][0-9A-Za-z_]*$')
146 HexPattern
= re
.compile(r
'0[xX][0-9a-fA-F]+$')
147 RegGuidPattern
= re
.compile(r
'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}')
149 SymbolPattern
= re
.compile("("
150 "\$\([A-Z][A-Z0-9_]*\)|\$\(\w+\.\w+\)|\w+\.\w+|"
152 "(?<=\W)AND(?=\W)|(?<=\W)OR(?=\W)|(?<=\W)NOT(?=\W)|(?<=\W)XOR(?=\W)|"
153 "(?<=\W)EQ(?=\W)|(?<=\W)NE(?=\W)|(?<=\W)GT(?=\W)|(?<=\W)LT(?=\W)|(?<=\W)GE(?=\W)|(?<=\W)LE(?=\W)"
157 def Eval(Operator
, Oprand1
, Oprand2
= None):
160 if Operator
not in ["in", "not in"] and (type(Oprand1
) == type('') or type(Oprand2
) == type('')):
161 if type(Oprand1
) == type(''):
162 if Oprand1
[0] in ['"', "'"] or Oprand1
.startswith('L"') or Oprand1
.startswith("L'")or Oprand1
.startswith('UINT'):
163 Oprand1
, Size
= ParseFieldValue(Oprand1
)
165 Oprand1
,Size
= ParseFieldValue('"' + Oprand1
+ '"')
166 if type(Oprand2
) == type(''):
167 if Oprand2
[0] in ['"', "'"] or Oprand2
.startswith('L"') or Oprand2
.startswith("L'") or Oprand2
.startswith('UINT'):
168 Oprand2
, Size
= ParseFieldValue(Oprand2
)
170 Oprand2
, Size
= ParseFieldValue('"' + Oprand2
+ '"')
171 if type(Oprand1
) == type('') or type(Oprand2
) == type(''):
172 raise BadExpression(ERR_STRING_EXPR
% Operator
)
173 if Operator
in ['in', 'not in']:
174 if type(Oprand1
) != type(''):
175 Oprand1
= IntToStr(Oprand1
)
176 if type(Oprand2
) != type(''):
177 Oprand2
= IntToStr(Oprand2
)
186 if Operator
in ["!", "NOT", "not"]:
187 if type(Oprand1
) == type(''):
188 raise BadExpression(ERR_STRING_EXPR
% Operator
)
189 EvalStr
= 'not Oprand1'
190 elif Operator
in ["~"]:
191 if type(Oprand1
) == type(''):
192 raise BadExpression(ERR_STRING_EXPR
% Operator
)
193 EvalStr
= '~ Oprand1'
195 if Operator
in ["+", "-"] and (type(True) in [type(Oprand1
), type(Oprand2
)]):
196 # Boolean in '+'/'-' will be evaluated but raise warning
197 WrnExp
= WrnExpression(WRN_BOOL_EXPR
)
198 elif type('') in [type(Oprand1
), type(Oprand2
)] and type(Oprand1
)!= type(Oprand2
):
199 # == between string and number/boolean will always return False, != return True
201 WrnExp
= WrnExpression(WRN_EQCMP_STR_OTHERS
)
202 WrnExp
.result
= False
204 elif Operator
== "!=":
205 WrnExp
= WrnExpression(WRN_NECMP_STR_OTHERS
)
209 raise BadExpression(ERR_RELCMP_STR_OTHERS
% Operator
)
210 elif TypeDict
[type(Oprand1
)] != TypeDict
[type(Oprand2
)]:
211 if Operator
in ["==", "!=", ">=", "<=", ">", "<"] and set((TypeDict
[type(Oprand1
)], TypeDict
[type(Oprand2
)])) == set((TypeDict
[type(True)], TypeDict
[type(0)])):
212 # comparison between number and boolean is allowed
214 elif Operator
in ['&', '|', '^', "and", "or"] and set((TypeDict
[type(Oprand1
)], TypeDict
[type(Oprand2
)])) == set((TypeDict
[type(True)], TypeDict
[type(0)])):
215 # bitwise and logical operation between number and boolean is allowed
218 raise BadExpression(ERR_EXPR_TYPE
)
219 if type(Oprand1
) == type('') and type(Oprand2
) == type(''):
220 if (Oprand1
.startswith('L"') and not Oprand2
.startswith('L"')) or \
221 (not Oprand1
.startswith('L"') and Oprand2
.startswith('L"')):
222 raise BadExpression(ERR_STRING_CMP
% (Oprand1
, Operator
, Oprand2
))
223 if 'in' in Operator
and type(Oprand2
) == type(''):
224 Oprand2
= Oprand2
.split()
225 EvalStr
= 'Oprand1 ' + Operator
+ ' Oprand2'
227 # Local symbols used by built in eval function
233 Val
= eval(EvalStr
, {}, Dict
)
234 except Exception, Excpt
:
235 raise BadExpression(str(Excpt
))
237 if Operator
in ['and', 'or']:
248 def __init__(self
, Expression
, SymbolTable
={}):
249 self
._NoProcess
= False
250 if type(Expression
) != type(''):
251 self
._Expr
= Expression
252 self
._NoProcess
= True
254 if Expression
.strip().startswith('{') and Expression
.strip().endswith('}'):
255 self
._Expr
= Expression
256 self
._NoProcess
= True
258 self
._Expr
= ReplaceExprMacro(Expression
.strip(),
260 SupportedInMacroList
)
262 if not self
._Expr
.strip():
263 raise BadExpression(ERR_EMPTY_EXPR
)
266 # The symbol table including PCD and macro mapping
268 self
._Symb
= copy
.deepcopy(SymbolTable
)
269 self
._Symb
.update(self
.LogicalOperators
)
271 self
._Len
= len(self
._Expr
)
273 self
._WarnExcept
= None
275 # Literal token without any conversion
276 self
._LiteralToken
= ''
278 # Public entry for this class
279 # @param RealValue: False: only evaluate if the expression is true or false, used for conditional expression
280 # True : return the evaluated str(value), used for PCD value
282 # @return: True or False if RealValue is False
283 # Evaluated value of string format if RealValue is True
285 def __call__(self
, RealValue
=False, Depth
=0):
291 self
._Expr
= self
._Expr
.strip()
292 if RealValue
and Depth
== 0:
293 self
._Token
= self
._Expr
294 if self
.__IsNumberToken
():
298 Token
= self
._GetToken
()
299 if type(Token
) == type('') and Token
.startswith('{') and Token
.endswith('}') and self
._Idx
>= self
._Len
:
301 except BadExpression
:
307 Val
= self
._ConExpr
()
309 if type(Val
) == type(''):
315 elif not Val
.startswith('L"') and not Val
.startswith('{') and not Val
.startswith("L'"):
317 RealVal
= '"' + RealVal
+ '"'
319 # The expression has been parsed, but the end of expression is not reached
320 # It means the rest does not comply EBNF of <Expression>
321 if self
._Idx
!= self
._Len
:
322 raise BadExpression(ERR_SNYTAX
% self
._Expr
[self
._Idx
:])
325 RetVal
= str(RealVal
)
332 self
._WarnExcept
.result
= RetVal
333 raise self
._WarnExcept
337 # Template function to parse binary operators which have same precedence
338 # Expr [Operator Expr]*
339 def _ExprFuncTemplate(self
, EvalFunc
, OpLst
):
341 while self
._IsOperator
(OpLst
):
345 if self
._IsOperator
(':'):
353 Val
= self
.Eval(Op
, Val
, EvalFunc())
354 except WrnExpression
, Warn
:
355 self
._WarnExcept
= Warn
360 return self
._ExprFuncTemplate
(self
._OrExpr
, ['?', ':'])
364 return self
._ExprFuncTemplate
(self
._AndExpr
, ["OR", "or", "||"])
368 return self
._ExprFuncTemplate
(self
._BitOr
, ["AND", "and", "&&"])
372 return self
._ExprFuncTemplate
(self
._BitXor
, ["|"])
376 return self
._ExprFuncTemplate
(self
._BitAnd
, ["XOR", "xor", "^"])
380 return self
._ExprFuncTemplate
(self
._EqExpr
, ["&"])
384 Val
= self
._RelExpr
()
385 while self
._IsOperator
(["==", "!=", "EQ", "NE", "IN", "in", "!", "NOT", "not"]):
387 if Op
in ["!", "NOT", "not"]:
388 if not self
._IsOperator
(["IN", "in"]):
389 raise BadExpression(ERR_REL_NOT_IN
)
390 Op
+= ' ' + self
._Token
392 Val
= self
.Eval(Op
, Val
, self
._RelExpr
())
393 except WrnExpression
, Warn
:
394 self
._WarnExcept
= Warn
400 return self
._ExprFuncTemplate
(self
._ShiftExpr
, ["<=", ">=", "<", ">", "LE", "GE", "LT", "GT"])
402 def _ShiftExpr(self
):
403 return self
._ExprFuncTemplate
(self
._AddExpr
, ["<<", ">>"])
407 return self
._ExprFuncTemplate
(self
._MulExpr
, ["+", "-"])
411 return self
._ExprFuncTemplate
(self
._UnaryExpr
, ["*", "/", "%"])
414 def _UnaryExpr(self
):
415 if self
._IsOperator
(["!", "NOT", "not"]):
416 Val
= self
._UnaryExpr
()
418 return self
.Eval('not', Val
)
419 except WrnExpression
, Warn
:
420 self
._WarnExcept
= Warn
422 if self
._IsOperator
(["~"]):
423 Val
= self
._UnaryExpr
()
425 return self
.Eval('~', Val
)
426 except WrnExpression
, Warn
:
427 self
._WarnExcept
= Warn
429 return self
._IdenExpr
()
431 # Parse identifier or encapsulated expression
433 Tk
= self
._GetToken
()
435 Val
= self
._ConExpr
()
437 # _GetToken may also raise BadExpression
438 if self
._GetToken
() != ')':
439 raise BadExpression(ERR_MATCH
)
440 except BadExpression
:
441 raise BadExpression(ERR_MATCH
)
445 # Skip whitespace or tab
447 for Char
in self
._Expr
[self
._Idx
:]:
448 if Char
not in ' \t':
452 # Try to convert string to number
453 def __IsNumberToken(self
):
455 if self
._Token
.lower()[0:2] == '0x' and len(self
._Token
) > 2:
457 if self
._Token
.startswith('"') or self
._Token
.startswith("'")\
458 or self
._Token
.startswith("L'") or self
._Token
.startswith('L"'):
460 for Index
in range(len(self
._Token
)):
461 if self
._Token
[Index
] in ['"', "'"]:
464 self
._Token
= ParseFieldValue(self
._Token
)[0]
467 self
._Token
= int(self
._Token
, Radix
)
475 def __GetArray(self
):
478 self
.__GetNList
(True)
479 Token
+= self
._LiteralToken
480 if self
._Idx
>= self
._Len
or self
._Expr
[self
._Idx
] != '}':
481 raise BadExpression(ERR_ARRAY_TOKEN
% Token
)
484 # All whitespace and tabs in array are already stripped.
485 IsArray
= IsGuid
= False
486 if len(Token
.split(',')) == 11 and len(Token
.split(',{')) == 2 \
487 and len(Token
.split('},')) == 1:
488 HexLen
= [11,6,6,5,4,4,4,4,4,4,6]
489 HexList
= Token
.split(',')
490 if HexList
[3].startswith('{') and \
491 not [Index
for Index
, Hex
in enumerate(HexList
) if len(Hex
) > HexLen
[Index
]]:
493 if Token
.lstrip('{').rstrip('}').find('{') == -1:
494 if not [Hex
for Hex
in Token
.lstrip('{').rstrip('}').split(',') if len(Hex
) > 4]:
496 if not IsArray
and not IsGuid
:
497 raise BadExpression(ERR_ARRAY_TOKEN
% Token
)
499 self
._Token
= self
._LiteralToken
= Token
502 # Parse string, the format must be: "..."
503 def __GetString(self
):
509 # Replace escape \\\", \"
510 Expr
= self
._Expr
[self
._Idx
:].replace('\\\\', '//').replace('\\\"', '\\\'')
513 if Ch
== '"' or Ch
== "'":
515 self
._Token
= self
._LiteralToken
= self
._Expr
[Idx
:self
._Idx
]
516 if self
._Token
.startswith('"') and not self
._Token
.endswith('"'):
517 raise BadExpression(ERR_STRING_TOKEN
% self
._Token
)
518 if self
._Token
.startswith("'") and not self
._Token
.endswith("'"):
519 raise BadExpression(ERR_STRING_TOKEN
% self
._Token
)
520 self
._Token
= self
._Token
[1:-1]
523 # Get token that is comprised by alphanumeric, underscore or dot(used by PCD)
524 # @param IsAlphaOp: Indicate if parsing general token or script operator(EQ, NE...)
525 def __GetIdToken(self
, IsAlphaOp
= False):
527 for Ch
in self
._Expr
[self
._Idx
:]:
528 if not self
.__IsIdChar
(Ch
) or ('?' in self
._Expr
and Ch
== ':'):
533 self
._Token
= self
._LiteralToken
= IdToken
535 self
.__ResolveToken
()
538 # Try to resolve token
539 def __ResolveToken(self
):
541 raise BadExpression(ERR_EMPTY_TOKEN
)
544 if self
.PcdPattern
.match(self
._Token
):
545 if self
._Token
not in self
._Symb
:
546 Ex
= BadExpression(ERR_PCD_RESOLVE
% self
._Token
)
549 self
._Token
= ValueExpression(self
._Symb
[self
._Token
], self
._Symb
)(True, self
._Depth
+1)
550 if type(self
._Token
) != type(''):
551 self
._LiteralToken
= hex(self
._Token
)
554 if self
._Token
.startswith('"'):
555 self
._Token
= self
._Token
[1:-1]
556 elif self
._Token
in ["FALSE", "false", "False"]:
558 elif self
._Token
in ["TRUE", "true", "True"]:
561 self
.__IsNumberToken
()
563 def __GetNList(self
, InArray
=False):
564 self
._GetSingleToken
()
565 if not self
.__IsHexLiteral
():
567 raise BadExpression(ERR_ARRAY_ELE
% self
._Token
)
571 Expr
= self
._Expr
[self
._Idx
:]
572 if not Expr
.startswith(','):
575 NList
= self
._LiteralToken
576 while Expr
.startswith(','):
580 self
._GetSingleToken
()
581 if not self
.__IsHexLiteral
():
582 raise BadExpression(ERR_ARRAY_ELE
% self
._Token
)
583 NList
+= self
._LiteralToken
585 Expr
= self
._Expr
[self
._Idx
:]
586 self
._Token
= self
._LiteralToken
= NList
589 def __IsHexLiteral(self
):
590 if self
._LiteralToken
.startswith('{') and \
591 self
._LiteralToken
.endswith('}'):
594 if self
.HexPattern
.match(self
._LiteralToken
):
595 Token
= self
._LiteralToken
[2:]
596 Token
= Token
.lstrip('0')
598 self
._LiteralToken
= '0x0'
600 self
._LiteralToken
= '0x' + Token
.lower()
605 return self
.__GetNList
()
609 return Ch
in '._:' or Ch
.isalnum()
612 def _GetSingleToken(self
):
614 Expr
= self
._Expr
[self
._Idx
:]
615 if Expr
.startswith('L"'):
618 UStr
= self
.__GetString
()
619 self
._Token
= 'L"' + UStr
+ '"'
620 self
._Token
, Size
= ParseFieldValue(self
._Token
)
622 elif Expr
.startswith("L'"):
625 UStr
= self
.__GetString
()
626 self
._Token
= "L'" + UStr
+ "'"
627 self
._Token
, Size
= ParseFieldValue(self
._Token
)
629 elif Expr
.startswith('"'):
630 UStr
= self
.__GetString
()
631 self
._Token
= '"' + UStr
+ '"'
632 self
._Token
, Size
= ParseFieldValue(self
._Token
)
634 elif Expr
.startswith("'"):
635 UStr
= self
.__GetString
()
636 self
._Token
= "'" + UStr
+ "'"
637 self
._Token
, Size
= ParseFieldValue(self
._Token
)
639 elif Expr
.startswith('UINT'):
640 Re
= re
.compile('(?:UINT8|UINT16|UINT32|UINT64)\((.+)\)')
642 RetValue
= Re
.search(Expr
).group(1)
644 raise BadExpression('Invalid Expression %s' % Expr
)
649 Prefix
= self
._Expr
[Idx
:self
._Idx
- 1]
652 TmpValue
= self
._Expr
[Idx
:self
._Idx
- 1]
653 TmpValue
= ValueExpression(TmpValue
)(True)
654 TmpValue
= '0x%x' % int(TmpValue
) if type(TmpValue
) != type('') else TmpValue
656 self
._Token
, Size
= ParseFieldValue(Prefix
+ '(' + TmpValue
+ ')')
662 Match
= self
.RegGuidPattern
.match(Expr
)
663 if Match
and not Expr
[Match
.end():Match
.end()+1].isalnum() \
664 and Expr
[Match
.end():Match
.end()+1] != '_':
665 self
._Idx
+= Match
.end()
666 self
._Token
= ValueExpression(GuidStringToGuidStructureString(Expr
[0:Match
.end()]))(True, self
._Depth
+1)
668 elif self
.__IsIdChar
(Ch
):
669 return self
.__GetIdToken
()
671 return self
.__GetString
()
673 return self
.__GetArray
()
674 elif Ch
== '(' or Ch
== ')':
679 raise BadExpression(ERR_VALID_TOKEN
% Expr
)
682 def _GetOperator(self
):
684 LegalOpLst
= ['&&', '||', '!=', '==', '>=', '<='] + self
.NonLetterOpLst
+ ['?',':']
687 Expr
= self
._Expr
[self
._Idx
:]
689 # Reach end of expression
693 # Script operator: LT, GT, LE, GE, EQ, NE, and, or, xor, not
694 if Expr
[0].isalpha():
695 return self
.__GetIdToken
(True)
697 # Start to get regular operator: +, -, <, > ...
698 if Expr
[0] not in self
.NonLetterOpLst
:
703 if Ch
in self
.NonLetterOpLst
:
704 if '!' == Ch
and OpToken
:
711 if OpToken
not in LegalOpLst
:
712 raise BadExpression(ERR_OPERATOR_UNSUPPORT
% OpToken
)
713 self
._Token
= OpToken
716 # Check if current token matches the operators given from OpList
717 def _IsOperator(self
, OpList
):
720 if self
._Token
in OpList
:
721 if self
._Token
in self
.LogicalOperators
:
722 self
._Token
= self
.LogicalOperators
[self
._Token
]
727 class ValueExpressionEx(ValueExpression
):
728 def __init__(self
, PcdValue
, PcdType
, SymbolTable
={}):
729 ValueExpression
.__init
__(self
, PcdValue
, SymbolTable
)
730 self
.PcdValue
= PcdValue
731 self
.PcdType
= PcdType
733 def __call__(self
, RealValue
=False, Depth
=0):
734 PcdValue
= self
.PcdValue
736 PcdValue
= ValueExpression
.__call
__(self
, RealValue
, Depth
)
737 except WrnExpression
, Value
:
738 PcdValue
= Value
.result
740 if PcdValue
== 'True':
742 if PcdValue
== 'False':
744 if self
.PcdType
in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
745 PcdValue
= PcdValue
.strip()
746 if type(PcdValue
) == type('') and PcdValue
.startswith('{') and PcdValue
.endswith('}'):
747 PcdValue
= PcdValue
[1:-1].split(',')
748 if type(PcdValue
) == type([]):
751 for Item
in PcdValue
:
752 if Item
.startswith('UINT16'):
754 elif Item
.startswith('UINT32'):
756 elif Item
.startswith('UINT64'):
760 Item
= ValueExpressionEx(Item
, self
.PcdType
, self
._Symb
)(True)
763 ItemValue
, ItemSize
= ParseFieldValue(Item
)
765 ItemValue
= ParseFieldValue(Item
)[0]
767 if type(ItemValue
) == type(''):
768 ItemValue
= int(ItemValue
, 16) if ItemValue
.startswith('0x') else int(ItemValue
)
770 TmpValue
= (ItemValue
<< (Size
* 8)) | TmpValue
771 Size
= Size
+ ItemSize
773 TmpValue
, Size
= ParseFieldValue(PcdValue
)
774 if type(TmpValue
) == type(''):
775 TmpValue
= int(TmpValue
)
777 PcdValue
= '0x%0{}X'.format(Size
) % (TmpValue
)
779 raise BadExpression('Type %s PCD Value is negative' % self
.PcdType
)
780 if self
.PcdType
== 'UINT8' and Size
> 1:
781 raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self
.PcdType
)
782 if self
.PcdType
== 'UINT16' and Size
> 2:
783 raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self
.PcdType
)
784 if self
.PcdType
== 'UINT32' and Size
> 4:
785 raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self
.PcdType
)
786 if self
.PcdType
== 'UINT64' and Size
> 8:
787 raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self
.PcdType
)
788 if self
.PcdType
in ['VOID*']:
790 TmpValue
= long(PcdValue
)
792 if TmpValue
.bit_length() == 0:
795 for I
in range((TmpValue
.bit_length() + 7) / 8):
796 TmpList
.append('0x%02x' % ((TmpValue
>> I
* 8) & 0xff))
797 PcdValue
= '{' + ', '.join(TmpList
) + '}'
799 if PcdValue
.strip().startswith('{'):
800 PcdValue
= PcdValue
.strip()[1:-1].strip()
803 TokenSpaceGuidName
= ''
804 if PcdValue
.startswith('GUID') and PcdValue
.endswith(')'):
806 TokenSpaceGuidName
= re
.search('GUID\((\w+)\)', PcdValue
).group(1)
809 if TokenSpaceGuidName
and TokenSpaceGuidName
in self
._Symb
:
810 PcdValue
= 'GUID(' + self
._Symb
[TokenSpaceGuidName
] + ')'
811 elif TokenSpaceGuidName
:
812 raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName
)
814 ListItem
, Size
= ParseFieldValue(PcdValue
)
815 elif PcdValue
.startswith('DEVICE_PATH') and PcdValue
.endswith(')'):
816 ListItem
, Size
= ParseFieldValue(PcdValue
)
818 ListItem
= PcdValue
.split(',')
820 if type(ListItem
) == type(0) or type(ListItem
) == type(0L):
821 for Index
in range(0, Size
):
822 ValueStr
+= '0x%02X' % (int(ListItem
) & 255)
825 PcdValue
= '{' + ValueStr
[:-2] + '}'
826 elif type(ListItem
) == type(''):
827 if ListItem
.startswith('{') and ListItem
.endswith('}'):
831 ReLabel
= re
.compile('LABEL\((\w+)\)')
832 ReOffset
= re
.compile('OFFSET_OF\((\w+)\)')
833 for Index
, Item
in enumerate(ListItem
):
837 LabelList
= ReLabel
.findall(Item
)
838 for Label
in LabelList
:
839 if Label
not in LabelDict
.keys():
840 LabelDict
[Label
] = str(Index
)
841 Item
= ReLabel
.sub('', Item
)
845 OffsetList
= ReOffset
.findall(Item
)
848 for Offset
in OffsetList
:
849 if Offset
in LabelDict
.keys():
850 Re
= re
.compile('OFFSET_OF\(%s\)'% Offset
)
851 Item
= Re
.sub(LabelDict
[Offset
], Item
)
853 raise BadExpression('%s not defined before use' % Offset
)
854 if Item
.startswith('UINT16'):
856 elif Item
.startswith('UINT32'):
858 elif Item
.startswith('UINT64'):
862 TmpValue
= ValueExpressionEx(Item
, self
.PcdType
, self
._Symb
)(True)
863 Item
= '0x%x' % TmpValue
if type(TmpValue
) != type('') else TmpValue
865 ItemValue
, ItemSize
= ParseFieldValue(Item
)
867 ItemValue
= ParseFieldValue(Item
)[0]
868 for I
in range(0, ItemSize
):
869 ValueStr
+= '0x%02X' % (int(ItemValue
) & 255)
875 PcdValue
= '{' + ValueStr
[:-2] + '}'
879 if __name__
== '__main__':
882 input = raw_input('Input expr: ')
886 print ValueExpression(input)(True)
887 print ValueExpression(input)(False)
888 except WrnExpression
, Ex
:
891 except Exception, Ex
: