From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Source/Python/UPT/Parser/DecParserMisc.py | 364 +++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 roms/edk2/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py (limited to 'roms/edk2/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py') diff --git a/roms/edk2/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py b/roms/edk2/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py new file mode 100644 index 000000000..27990467d --- /dev/null +++ b/roms/edk2/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py @@ -0,0 +1,364 @@ +## @file +# This file is used to define helper class and function for DEC parser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +DecParserMisc +''' + +## Import modules +# +import os +import Logger.Log as Logger +from Logger.ToolError import FILE_PARSE_FAILURE +from Logger import StringTable as ST +from Library.DataType import TAB_COMMENT_SPLIT +from Library.DataType import TAB_COMMENT_EDK1_SPLIT +from Library.ExpressionValidate import IsValidBareCString +from Library.ParserValidate import IsValidCFormatGuid +from Library.ExpressionValidate import IsValidFeatureFlagExp +from Library.ExpressionValidate import IsValidLogicalExpr +from Library.ExpressionValidate import IsValidStringTest +from Library.Misc import CheckGuidRegFormat + +TOOL_NAME = 'DecParser' +VERSION_PATTERN = '[0-9]+(\.[0-9]+)?' +CVAR_PATTERN = '[_a-zA-Z][a-zA-Z0-9_]*' +PCD_TOKEN_PATTERN = '(0[xX]0*[a-fA-F0-9]{1,8})|([0-9]+)' +MACRO_PATTERN = '[A-Z][_A-Z0-9]*' + +## FileContent +# Class to hold DEC file information +# +class FileContent: + def __init__(self, Filename, FileContent2): + self.Filename = Filename + self.PackagePath, self.PackageFile = os.path.split(Filename) + self.LineIndex = 0 + self.CurrentLine = '' + self.NextLine = '' + self.HeadComment = [] + self.TailComment = [] + self.CurrentScope = None + self.Content = FileContent2 + self.Macros = {} + self.FileLines = len(FileContent2) + + def GetNextLine(self): + if self.LineIndex >= self.FileLines: + return '' + Line = self.Content[self.LineIndex] + self.LineIndex += 1 + return Line + + def UndoNextLine(self): + if self.LineIndex > 0: + self.LineIndex -= 1 + + def ResetNext(self): + self.HeadComment = [] + self.TailComment = [] + self.NextLine = '' + + def SetNext(self, Line, HeadComment, TailComment): + self.NextLine = Line + self.HeadComment = HeadComment + self.TailComment = TailComment + + def IsEndOfFile(self): + return self.LineIndex >= self.FileLines + + +## StripRoot +# +# Strip root path +# +# @param Root: Root must be absolute path +# @param Path: Path to be stripped +# +def StripRoot(Root, Path): + OrigPath = Path + Root = os.path.normpath(Root) + Path = os.path.normpath(Path) + if not os.path.isabs(Root): + return OrigPath + if Path.startswith(Root): + Path = Path[len(Root):] + if Path and Path[0] == os.sep: + Path = Path[1:] + return Path + return OrigPath + +## CleanString +# +# Split comments in a string +# Remove spaces +# +# @param Line: The string to be cleaned +# @param CommentCharacter: Comment char, used to ignore comment content, +# default is DataType.TAB_COMMENT_SPLIT +# +def CleanString(Line, CommentCharacter=TAB_COMMENT_SPLIT, \ + AllowCppStyleComment=False): + # + # remove whitespace + # + Line = Line.strip() + # + # Replace EDK1's comment character + # + if AllowCppStyleComment: + Line = Line.replace(TAB_COMMENT_EDK1_SPLIT, CommentCharacter) + # + # separate comments and statements + # + Comment = '' + InQuote = False + for Index in range(0, len(Line)): + if Line[Index] == '"': + InQuote = not InQuote + continue + if Line[Index] == CommentCharacter and not InQuote: + Comment = Line[Index:].strip() + Line = Line[0:Index].strip() + break + + return Line, Comment + + +## IsValidNumValUint8 +# +# Check if Token is NumValUint8: ::= {} {} {} +# +# @param Token: Token to be checked +# +def IsValidNumValUint8(Token): + Valid = True + Cause = "" + TokenValue = None + Token = Token.strip() + if Token.lower().startswith('0x'): + Base = 16 + else: + Base = 10 + try: + TokenValue = int(Token, Base) + except BaseException: + Valid, Cause = IsValidLogicalExpr(Token, True) + if Cause: + pass + if not Valid: + return False + if TokenValue and (TokenValue < 0 or TokenValue > 0xFF): + return False + else: + return True + +## IsValidNList +# +# Check if Value has the format of ["," ]{0,} +# ::= {} {} {} +# +# @param Value: Value to be checked +# +def IsValidNList(Value): + Par = ParserHelper(Value) + if Par.End(): + return False + while not Par.End(): + Token = Par.GetToken(',') + if not IsValidNumValUint8(Token): + return False + if Par.Expect(','): + if Par.End(): + return False + continue + else: + break + return Par.End() + +## IsValidCArray +# +# check Array is valid +# +# @param Array: The input Array +# +def IsValidCArray(Array): + Par = ParserHelper(Array) + if not Par.Expect('{'): + return False + if Par.End(): + return False + while not Par.End(): + Token = Par.GetToken(',}') + # + # ShortNum, UINT8, Expression + # + if not IsValidNumValUint8(Token): + return False + if Par.Expect(','): + if Par.End(): + return False + continue + elif Par.Expect('}'): + # + # End of C array + # + break + else: + return False + return Par.End() + +## IsValidPcdDatum +# +# check PcdDatum is valid +# +# @param Type: The pcd Type +# @param Value: The pcd Value +# +def IsValidPcdDatum(Type, Value): + if not Value: + return False, ST.ERR_DECPARSE_PCD_VALUE_EMPTY + Valid = True + Cause = "" + if Type not in ["UINT8", "UINT16", "UINT32", "UINT64", "VOID*", "BOOLEAN"]: + return False, ST.ERR_DECPARSE_PCD_TYPE + if Type == "VOID*": + if not ((Value.startswith('L"') or Value.startswith('"') and \ + Value.endswith('"')) + or (IsValidCArray(Value)) or (IsValidCFormatGuid(Value)) \ + or (IsValidNList(Value)) or (CheckGuidRegFormat(Value)) + ): + return False, ST.ERR_DECPARSE_PCD_VOID % (Value, Type) + RealString = Value[Value.find('"') + 1 :-1] + if RealString: + if not IsValidBareCString(RealString): + return False, ST.ERR_DECPARSE_PCD_VOID % (Value, Type) + elif Type == 'BOOLEAN': + if Value in ['TRUE', 'FALSE', 'true', 'false', 'True', 'False', + '0x1', '0x01', '1', '0x0', '0x00', '0']: + return True, "" + Valid, Cause = IsValidStringTest(Value, True) + if not Valid: + Valid, Cause = IsValidFeatureFlagExp(Value, True) + if not Valid: + return False, Cause + else: + if Value and (Value[0] == '-' or Value[0] == '+'): + return False, ST.ERR_DECPARSE_PCD_INT_NEGTIVE % (Value, Type) + try: + StrVal = Value + if Value and not Value.startswith('0x') \ + and not Value.startswith('0X'): + Value = Value.lstrip('0') + if not Value: + return True, "" + Value = int(Value, 0) + MAX_VAL_TYPE = {"BOOLEAN": 0x01, 'UINT8': 0xFF, 'UINT16': 0xFFFF, 'UINT32': 0xFFFFFFFF, + 'UINT64': 0xFFFFFFFFFFFFFFFF} + if Value > MAX_VAL_TYPE[Type]: + return False, ST.ERR_DECPARSE_PCD_INT_EXCEED % (StrVal, Type) + except BaseException: + Valid, Cause = IsValidLogicalExpr(Value, True) + if not Valid: + return False, Cause + + return True, "" + +## ParserHelper +# +class ParserHelper: + def __init__(self, String, File=''): + self._String = String + self._StrLen = len(String) + self._Index = 0 + self._File = File + + ## End + # + # End + # + def End(self): + self.__SkipWhitespace() + return self._Index >= self._StrLen + + ## __SkipWhitespace + # + # Skip whitespace + # + def __SkipWhitespace(self): + for Char in self._String[self._Index:]: + if Char not in ' \t': + break + self._Index += 1 + + ## Expect + # + # Expect char in string + # + # @param ExpectChar: char expected in index of string + # + def Expect(self, ExpectChar): + self.__SkipWhitespace() + for Char in self._String[self._Index:]: + if Char != ExpectChar: + return False + else: + self._Index += 1 + return True + # + # Index out of bound of String + # + return False + + ## GetToken + # + # Get token until encounter StopChar, front whitespace is consumed + # + # @param StopChar: Get token until encounter char in StopChar + # @param StkipPair: Only can be ' or ", StopChar in SkipPair are skipped + # + def GetToken(self, StopChar='.,|\t ', SkipPair='"'): + self.__SkipWhitespace() + PreIndex = self._Index + InQuote = False + LastChar = '' + for Char in self._String[self._Index:]: + if Char == SkipPair and LastChar != '\\': + InQuote = not InQuote + if Char in StopChar and not InQuote: + break + self._Index += 1 + if Char == '\\' and LastChar == '\\': + LastChar = '' + else: + LastChar = Char + return self._String[PreIndex:self._Index] + + ## AssertChar + # + # Assert char at current index of string is AssertChar, or will report + # error message + # + # @param AssertChar: AssertChar + # @param ErrorString: ErrorString + # @param ErrorLineNum: ErrorLineNum + # + def AssertChar(self, AssertChar, ErrorString, ErrorLineNum): + if not self.Expect(AssertChar): + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._File, + Line=ErrorLineNum, ExtraData=ErrorString) + + ## AssertEnd + # + # @param ErrorString: ErrorString + # @param ErrorLineNum: ErrorLineNum + # + def AssertEnd(self, ErrorString, ErrorLineNum): + self.__SkipWhitespace() + if self._Index != self._StrLen: + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._File, + Line=ErrorLineNum, ExtraData=ErrorString) -- cgit 1.2.3-korg