Home | History | Annotate | Download | only in Parser
      1 ## @file

      2 # This file is used to parse DEC file. It will consumed by DecParser

      3 #

      4 # Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>

      5 #

      6 # This program and the accompanying materials are licensed and made available 

      7 # under the terms and conditions of the BSD License which accompanies this 

      8 # distribution. The full text of the license may be found at 

      9 # http://opensource.org/licenses/bsd-license.php

     10 #

     11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     13 '''
     14 DecParser
     15 '''
     16 ## Import modules

     17 #

     18 import Logger.Log as Logger
     19 from Logger.ToolError import FILE_PARSE_FAILURE
     20 from Logger.ToolError import FILE_OPEN_FAILURE
     21 from Logger import StringTable as ST
     22 from Logger.ToolError import FORMAT_INVALID
     23 
     24 import Library.DataType as DT
     25 from Library.ParserValidate import IsValidToken
     26 from Library.ParserValidate import IsValidPath
     27 from Library.ParserValidate import IsValidCFormatGuid
     28 from Library.ParserValidate import IsValidIdString
     29 from Library.ParserValidate import IsValidUserId
     30 from Library.ParserValidate import IsValidArch
     31 from Library.ParserValidate import IsValidWord
     32 from Library.ParserValidate import IsValidDecVersionVal
     33 from Parser.DecParserMisc import TOOL_NAME
     34 from Parser.DecParserMisc import CleanString
     35 from Parser.DecParserMisc import IsValidPcdDatum
     36 from Parser.DecParserMisc import ParserHelper
     37 from Parser.DecParserMisc import StripRoot
     38 from Parser.DecParserMisc import VERSION_PATTERN
     39 from Parser.DecParserMisc import CVAR_PATTERN
     40 from Parser.DecParserMisc import PCD_TOKEN_PATTERN
     41 from Parser.DecParserMisc import MACRO_PATTERN
     42 from Parser.DecParserMisc import FileContent
     43 from Object.Parser.DecObject import _DecComments
     44 from Object.Parser.DecObject import DecDefineObject
     45 from Object.Parser.DecObject import DecDefineItemObject
     46 from Object.Parser.DecObject import DecIncludeObject
     47 from Object.Parser.DecObject import DecIncludeItemObject
     48 from Object.Parser.DecObject import DecLibraryclassObject
     49 from Object.Parser.DecObject import DecLibraryclassItemObject
     50 from Object.Parser.DecObject import DecGuidObject
     51 from Object.Parser.DecObject import DecPpiObject
     52 from Object.Parser.DecObject import DecProtocolObject
     53 from Object.Parser.DecObject import DecGuidItemObject
     54 from Object.Parser.DecObject import DecUserExtensionObject
     55 from Object.Parser.DecObject import DecUserExtensionItemObject
     56 from Object.Parser.DecObject import DecPcdObject
     57 from Object.Parser.DecObject import DecPcdItemObject
     58 from Library.Misc import GuidStructureStringToGuidString
     59 from Library.Misc import CheckGuidRegFormat
     60 from Library.String import ReplaceMacro
     61 from Library.String import GetSplitValueList
     62 from Library.String import gMACRO_PATTERN
     63 from Library.String import ConvertSpecialChar
     64 from Library.CommentParsing import ParsePcdErrorCode
     65 
     66 ##

     67 # _DecBase class for parsing

     68 #

     69 class _DecBase:
     70     def __init__(self, RawData):
     71         self._RawData = RawData
     72         self._ItemDict = {}
     73         self._LocalMacro = {}
     74         #

     75         # Data parsed by 'self' are saved to this object

     76         #

     77         self.ItemObject = None
     78     
     79     def GetDataObject(self):
     80         return self.ItemObject
     81     
     82     def GetLocalMacro(self):
     83         return self._LocalMacro
     84     
     85     ## BlockStart

     86     #

     87     # Called if a new section starts

     88     #

     89     def BlockStart(self):
     90         self._LocalMacro = {}
     91     
     92     ## _CheckReDefine

     93     #

     94     # @param Key: to be checked if multi-defined

     95     # @param Scope: Format: [[SectionName, Arch], ...]. 

     96     #               If scope is none, use global scope

     97     #

     98     def _CheckReDefine(self, Key, Scope = None):
     99         if not Scope:
    100             Scope = self._RawData.CurrentScope
    101             return
    102         
    103         SecArch = []
    104         #

    105         # Copy scope to SecArch, avoid Scope be changed outside

    106         #

    107         SecArch[0:1] = Scope[:]
    108         if Key not in self._ItemDict:
    109             self._ItemDict[Key] = [[SecArch, self._RawData.LineIndex]]
    110             return
    111         
    112         for Value in self._ItemDict[Key]:
    113             for SubValue in Scope:
    114                 #

    115                 # If current is common section

    116                 #

    117                 if SubValue[-1] == 'COMMON':
    118                     for Other in Value[0]:
    119                         # Key in common cannot be redefined in other arches

    120                         # [:-1] means stripping arch info

    121                         if Other[:-1] == SubValue[:-1]:
    122                             self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1]))
    123                             return
    124                     continue
    125                 CommonScope = []
    126                 CommonScope[0:1] = SubValue
    127                 CommonScope[-1] = 'COMMON'
    128                 #

    129                 # Cannot be redefined if this key already defined in COMMON Or defined in same arch

    130                 #

    131                 if SubValue in Value[0] or CommonScope in Value[0]:
    132                     self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1]))
    133                     return
    134         self._ItemDict[Key].append([SecArch, self._RawData.LineIndex])
    135     
    136     ## CheckRequiredFields

    137     # Some sections need to check if some fields exist, define section for example

    138     # Derived class can re-implement, top parser will call this function after all parsing done

    139     #  

    140     def CheckRequiredFields(self):
    141         if self._RawData:
    142             pass
    143         return True
    144     
    145     ## IsItemRequired

    146     # In DEC spec, sections must have at least one statement except user 

    147     # extension.

    148     # For example: "[guids" [<attribs>] "]" <EOL> <statements>+

    149     # sub class can override this method to indicate if statement is a must.

    150     #

    151     def _IsStatementRequired(self):
    152         if self._RawData:
    153             pass
    154         return False
    155     
    156     def _LoggerError(self, ErrorString):
    157         Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, 
    158                      Line = self._RawData.LineIndex,
    159                      ExtraData=ErrorString + ST.ERR_DECPARSE_LINE % self._RawData.CurrentLine)
    160     
    161     def _ReplaceMacro(self, String):
    162         if gMACRO_PATTERN.findall(String):
    163             String = ReplaceMacro(String, self._LocalMacro, False,
    164                                   FileName = self._RawData.Filename,
    165                                   Line = ['', self._RawData.LineIndex])
    166             String = ReplaceMacro(String, self._RawData.Macros, False,
    167                                   FileName = self._RawData.Filename,
    168                                   Line = ['', self._RawData.LineIndex])
    169             MacroUsed = gMACRO_PATTERN.findall(String)
    170             if MacroUsed:
    171                 Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE,
    172                              File=self._RawData.Filename, 
    173                              Line = self._RawData.LineIndex,
    174                              ExtraData = ST.ERR_DECPARSE_MACRO_RESOLVE % (str(MacroUsed), String))
    175         return String
    176     
    177     def _MacroParser(self, String):
    178         TokenList = GetSplitValueList(String, ' ', 1)
    179         if len(TokenList) < 2 or TokenList[1] == '':
    180             self._LoggerError(ST.ERR_DECPARSE_MACRO_PAIR)
    181 
    182         TokenList = GetSplitValueList(TokenList[1], DT.TAB_EQUAL_SPLIT, 1)
    183         if TokenList[0] == '':
    184             self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME)
    185         elif not IsValidToken(MACRO_PATTERN, TokenList[0]):
    186             self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME_UPPER % TokenList[0])
    187         
    188         if len(TokenList) == 1:
    189             self._LocalMacro[TokenList[0]] = ''
    190         else:
    191             self._LocalMacro[TokenList[0]] = self._ReplaceMacro(TokenList[1])
    192 
    193     ## _ParseItem

    194     #

    195     # Parse specified item, this function must be derived by subclass

    196     #

    197     def _ParseItem(self):
    198         if self._RawData:
    199             pass
    200         #

    201         # Should never be called

    202         #

    203         return None
    204 
    205     
    206     ## _TailCommentStrategy

    207     #

    208     # This function can be derived to parse tail comment

    209     # default is it will not consume any lines

    210     #

    211     # @param Comment: Comment of current line

    212     #

    213     def _TailCommentStrategy(self, Comment):
    214         if Comment:
    215             pass
    216         if self._RawData:
    217             pass
    218         return False
    219     
    220     ## _StopCurrentParsing

    221     #

    222     # Called in Parse if current parsing should be stopped when encounter some

    223     # keyword

    224     # Default is section start and end

    225     #

    226     # @param Line: Current line

    227     #

    228     def _StopCurrentParsing(self, Line):
    229         if self._RawData:
    230             pass
    231         return Line[0] == DT.TAB_SECTION_START and Line[-1] == DT.TAB_SECTION_END
    232     
    233     ## _TryBackSlash

    234     #

    235     # Split comment and DEC content, concatenate lines if end of char is '\'

    236     #

    237     # @param ProcessedLine: ProcessedLine line

    238     # @param ProcessedComments: ProcessedComments line

    239     #

    240     def _TryBackSlash(self, ProcessedLine, ProcessedComments):
    241         CatLine = ''
    242         Comment = ''
    243         Line = ProcessedLine
    244         CommentList = ProcessedComments
    245         while not self._RawData.IsEndOfFile():
    246             if Line == '':
    247                 self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
    248                 break
    249             
    250             if Comment:
    251                 CommentList.append((Comment, self._RawData.LineIndex))
    252             if Line[-1] != DT.TAB_SLASH:
    253                 CatLine += Line
    254                 break
    255             elif len(Line) < 2 or Line[-2] != ' ':
    256                 self._LoggerError(ST.ERR_DECPARSE_BACKSLASH)
    257             else:
    258                 CatLine += Line[:-1]
    259                 Line, Comment = CleanString(self._RawData.GetNextLine())
    260         #

    261         # Reach end of content

    262         #

    263         if self._RawData.IsEndOfFile():
    264             if not CatLine:
    265                 if ProcessedLine[-1] == DT.TAB_SLASH:
    266                     self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
    267                 CatLine = ProcessedLine
    268             else:
    269                 if not Line or Line[-1] == DT.TAB_SLASH:
    270                     self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
    271                 CatLine += Line
    272          
    273         self._RawData.CurrentLine = self._ReplaceMacro(CatLine)
    274         return CatLine, CommentList
    275     
    276     ## Parse

    277     # This is a template method in which other member functions which might 

    278     # override by sub class are called. It is responsible for reading file 

    279     # line by line, and call other member functions to parse. This function

    280     # should not be re-implement by sub class.

    281     #

    282     def Parse(self):
    283         HeadComments = []
    284         TailComments = []
    285         
    286         #======================================================================

    287         # CurComments may pointer to HeadComments or TailComments

    288         #======================================================================

    289         CurComments = HeadComments
    290         CurObj = None
    291         ItemNum = 0
    292         FromBuf = False
    293         
    294         #======================================================================

    295         # Used to report error information if empty section found

    296         #======================================================================

    297         Index = self._RawData.LineIndex
    298         LineStr = self._RawData.CurrentLine
    299         while not self._RawData.IsEndOfFile() or self._RawData.NextLine:
    300             if self._RawData.NextLine:
    301                 #==============================================================

    302                 # Have processed line in buffer

    303                 #==============================================================

    304                 Line = self._RawData.NextLine
    305                 HeadComments.extend(self._RawData.HeadComment)
    306                 TailComments.extend(self._RawData.TailComment)
    307                 self._RawData.ResetNext()
    308                 Comment = ''
    309                 FromBuf = True
    310             else:
    311                 #==============================================================

    312                 # No line in buffer, read next line

    313                 #==============================================================

    314                 Line, Comment = CleanString(self._RawData.GetNextLine())
    315                 FromBuf = False
    316             if Line:
    317                 if not FromBuf and CurObj and TailComments:
    318                     #==========================================================

    319                     # Set tail comments to previous statement if not empty.

    320                     #==========================================================

    321                     CurObj.SetTailComment(CurObj.GetTailComment()+TailComments)
    322                 
    323                 if not FromBuf:
    324                     del TailComments[:]
    325                 CurComments = TailComments
    326                 Comments = []
    327                 if Comment:
    328                     Comments = [(Comment, self._RawData.LineIndex)]
    329                 
    330                 #==============================================================

    331                 # Try if last char of line has backslash

    332                 #==============================================================

    333                 Line, Comments = self._TryBackSlash(Line, Comments)
    334                 CurComments.extend(Comments)
    335                 
    336                 #==============================================================

    337                 # Macro found

    338                 #==============================================================

    339                 if Line.startswith('DEFINE '):
    340                     self._MacroParser(Line)
    341                     del HeadComments[:]
    342                     del TailComments[:]
    343                     CurComments = HeadComments
    344                     continue
    345                 
    346                 if self._StopCurrentParsing(Line):
    347                     #==========================================================

    348                     # This line does not belong to this parse,

    349                     # Save it, can be used by next parse

    350                     #==========================================================

    351                     self._RawData.SetNext(Line, HeadComments, TailComments)
    352                     break
    353                 
    354                 Obj = self._ParseItem()
    355                 ItemNum += 1
    356                 if Obj:
    357                     Obj.SetHeadComment(Obj.GetHeadComment()+HeadComments)
    358                     Obj.SetTailComment(Obj.GetTailComment()+TailComments)
    359                     del HeadComments[:]
    360                     del TailComments[:]
    361                     CurObj = Obj
    362                 else:
    363                     CurObj = None
    364             else:
    365                 if id(CurComments) == id(TailComments):
    366                     #==========================================================

    367                     # Check if this comment belongs to tail comment

    368                     #==========================================================

    369                     if not self._TailCommentStrategy(Comment):
    370                         CurComments = HeadComments
    371 
    372                 if Comment:
    373                     CurComments.append(((Comment, self._RawData.LineIndex)))
    374                 else:
    375                     del CurComments[:]
    376         
    377         if self._IsStatementRequired() and ItemNum == 0:
    378             Logger.Error(
    379                     TOOL_NAME, FILE_PARSE_FAILURE,
    380                     File=self._RawData.Filename,
    381                     Line=Index,
    382                     ExtraData=ST.ERR_DECPARSE_STATEMENT_EMPTY % LineStr
    383             )
    384 
    385 ## _DecDefine

    386 # Parse define section

    387 #

    388 class _DecDefine(_DecBase):
    389     def __init__(self, RawData):
    390         _DecBase.__init__(self, RawData)
    391         self.ItemObject = DecDefineObject(RawData.Filename)
    392         self._LocalMacro = self._RawData.Macros
    393         self._DefSecNum = 0
    394         
    395         #

    396         # Each field has a function to validate

    397         #

    398         self.DefineValidation = {
    399             DT.TAB_DEC_DEFINES_DEC_SPECIFICATION   :   self._SetDecSpecification,
    400             DT.TAB_DEC_DEFINES_PACKAGE_NAME        :   self._SetPackageName,
    401             DT.TAB_DEC_DEFINES_PACKAGE_GUID        :   self._SetPackageGuid,
    402             DT.TAB_DEC_DEFINES_PACKAGE_VERSION     :   self._SetPackageVersion,
    403             DT.TAB_DEC_DEFINES_PKG_UNI_FILE        :   self._SetPackageUni,
    404         }
    405     
    406     def BlockStart(self):
    407         self._DefSecNum += 1
    408         if self._DefSecNum > 1:
    409             self._LoggerError(ST.ERR_DECPARSE_DEFINE_MULTISEC)
    410     
    411     ## CheckRequiredFields

    412     #

    413     # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME

    414     #                        PACKAGE_GUID, PACKAGE_VERSION

    415     #

    416     def CheckRequiredFields(self):
    417         Ret = False
    418         if self.ItemObject.GetPackageSpecification() == '':
    419             Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, 
    420                          ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION)
    421         elif self.ItemObject.GetPackageName() == '':
    422             Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, 
    423                          ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_NAME)
    424         elif self.ItemObject.GetPackageGuid() == '':
    425             Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, 
    426                          ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_GUID)
    427         elif self.ItemObject.GetPackageVersion() == '':
    428             Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, 
    429                          ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION)
    430         else:
    431             Ret = True
    432         return Ret
    433     
    434     def _ParseItem(self):
    435         Line = self._RawData.CurrentLine
    436         TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1)
    437         if TokenList[0] == DT.TAB_DEC_DEFINES_PKG_UNI_FILE:
    438             self.DefineValidation[TokenList[0]](TokenList[1])
    439         elif len(TokenList) < 2:
    440             self._LoggerError(ST.ERR_DECPARSE_DEFINE_FORMAT)
    441         elif TokenList[0] not in self.DefineValidation:
    442             self._LoggerError(ST.ERR_DECPARSE_DEFINE_UNKNOWKEY % TokenList[0])
    443         else:
    444             self.DefineValidation[TokenList[0]](TokenList[1])
    445         
    446         DefineItem = DecDefineItemObject()
    447         DefineItem.Key   = TokenList[0]
    448         DefineItem.Value = TokenList[1]
    449         self.ItemObject.AddItem(DefineItem, self._RawData.CurrentScope)
    450         return DefineItem
    451     
    452     def _SetDecSpecification(self, Token):
    453         if self.ItemObject.GetPackageSpecification():
    454             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION)
    455         if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token):
    456             if not IsValidDecVersionVal(Token):
    457                 self._LoggerError(ST.ERR_DECPARSE_DEFINE_SPEC)
    458         self.ItemObject.SetPackageSpecification(Token)
    459     
    460     def _SetPackageName(self, Token):
    461         if self.ItemObject.GetPackageName():
    462             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_NAME)
    463         if not IsValidWord(Token):
    464             self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGNAME)
    465         self.ItemObject.SetPackageName(Token)
    466     
    467     def _SetPackageGuid(self, Token):
    468         if self.ItemObject.GetPackageGuid():
    469             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_GUID)
    470         if not CheckGuidRegFormat(Token):
    471             self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID)
    472         self.ItemObject.SetPackageGuid(Token)
    473     
    474     def _SetPackageVersion(self, Token):
    475         if self.ItemObject.GetPackageVersion():
    476             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION)
    477         if not IsValidToken(VERSION_PATTERN, Token):
    478             self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGVERSION)
    479         else:
    480             if not DT.TAB_SPLIT in Token:
    481                 Token = Token + '.0'
    482             self.ItemObject.SetPackageVersion(Token)
    483             
    484     def _SetPackageUni(self, Token):
    485         if self.ItemObject.GetPackageUniFile():
    486             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PKG_UNI_FILE)
    487         self.ItemObject.SetPackageUniFile(Token)
    488 
    489 ## _DecInclude

    490 #

    491 # Parse include section

    492 #

    493 class _DecInclude(_DecBase):
    494     def __init__(self, RawData):
    495         _DecBase.__init__(self, RawData)
    496         self.ItemObject = DecIncludeObject(RawData.Filename)
    497     
    498     def _ParseItem(self):
    499         Line = self._RawData.CurrentLine
    500         
    501         if not IsValidPath(Line, self._RawData.PackagePath):
    502             self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Line) 
    503         
    504         Item = DecIncludeItemObject(StripRoot(self._RawData.PackagePath, Line), self._RawData.PackagePath)
    505         self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
    506         return Item
    507 
    508 ## _DecLibraryclass

    509 #

    510 # Parse library class section

    511 #

    512 class _DecLibraryclass(_DecBase):
    513     def __init__(self, RawData):
    514         _DecBase.__init__(self, RawData)
    515         self.ItemObject = DecLibraryclassObject(RawData.Filename)
    516     
    517     def _ParseItem(self):
    518         Line = self._RawData.CurrentLine
    519         TokenList = GetSplitValueList(Line, DT.TAB_VALUE_SPLIT)
    520         if len(TokenList) != 2:
    521             self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_SPLIT) 
    522         if TokenList[0] == '' or TokenList[1] == '':
    523             self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_EMPTY)
    524         if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList[0]):
    525             self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_LIB)
    526         
    527         self._CheckReDefine(TokenList[0])
    528         
    529         Value = TokenList[1]
    530         #

    531         # Must end with .h

    532         #

    533         if not Value.endswith('.h'):
    534             self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_PATH_EXT)
    535         
    536         #

    537         # Path must be existed

    538         #

    539         if not IsValidPath(Value, self._RawData.PackagePath):
    540             self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Value)
    541         
    542         Item = DecLibraryclassItemObject(TokenList[0], StripRoot(self._RawData.PackagePath, Value),
    543                                          self._RawData.PackagePath)
    544         self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
    545         return Item
    546 
    547 ## _DecPcd

    548 #

    549 # Parse PCD section

    550 #

    551 class _DecPcd(_DecBase):
    552     def __init__(self, RawData):
    553         _DecBase.__init__(self, RawData)
    554         self.ItemObject = DecPcdObject(RawData.Filename)
    555         #

    556         # Used to check duplicate token

    557         # Key is token space and token number (integer), value is C name

    558         #

    559         self.TokenMap = {}
    560     
    561     def _ParseItem(self):
    562         Line = self._RawData.CurrentLine
    563         TokenList = Line.split(DT.TAB_VALUE_SPLIT)
    564         if len(TokenList) < 4:
    565             self._LoggerError(ST.ERR_DECPARSE_PCD_SPLIT)
    566         
    567         #

    568         # Token space guid C name

    569         #

    570         PcdName = GetSplitValueList(TokenList[0], DT.TAB_SPLIT)
    571         if len(PcdName) != 2 or PcdName[0] == '' or PcdName[1] == '':
    572             self._LoggerError(ST.ERR_DECPARSE_PCD_NAME)
    573         
    574         Guid = PcdName[0]
    575         if not IsValidToken(CVAR_PATTERN, Guid):
    576             self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID)
    577         
    578         #

    579         # PCD C name

    580         #

    581         CName = PcdName[1]
    582         if not IsValidToken(CVAR_PATTERN, CName):
    583             self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_PCDCNAME)
    584         
    585         self._CheckReDefine(Guid + DT.TAB_SPLIT + CName)
    586         
    587         #

    588         # Default value, may be C array, string or number

    589         #

    590         Data = DT.TAB_VALUE_SPLIT.join(TokenList[1:-2]).strip()
    591         
    592         #

    593         # PCD data type

    594         #

    595         DataType = TokenList[-2].strip()
    596         Valid, Cause = IsValidPcdDatum(DataType, Data)
    597         if not Valid:
    598             self._LoggerError(Cause)
    599         PcdType = self._RawData.CurrentScope[0][0]
    600         if PcdType == DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() and DataType != 'BOOLEAN':
    601             self._LoggerError(ST.ERR_DECPARSE_PCD_FEATUREFLAG)
    602         #

    603         # Token value is the last element in list.

    604         #

    605         Token = TokenList[-1].strip()
    606         if not IsValidToken(PCD_TOKEN_PATTERN, Token):
    607             self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN % Token)
    608         elif not Token.startswith('0x') and not Token.startswith('0X'):
    609             if long(Token) > 4294967295:
    610                 self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_INT % Token)
    611             Token = hex(long(Token))[:-1]
    612         
    613         IntToken = long(Token, 0)
    614         if (Guid, IntToken) in self.TokenMap:
    615             if self.TokenMap[Guid, IntToken] != CName:
    616                 self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_UNIQUE%(Token))
    617         else:
    618             self.TokenMap[Guid, IntToken] = CName
    619         
    620         Item = DecPcdItemObject(Guid, CName, Data, DataType, Token)
    621         self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
    622         return Item
    623         
    624 ## _DecGuid

    625 #

    626 # Parse GUID, PPI, Protocol section

    627 #

    628 class _DecGuid(_DecBase):
    629     def __init__(self, RawData):
    630         _DecBase.__init__(self, RawData)
    631         self.GuidObj = DecGuidObject(RawData.Filename)
    632         self.PpiObj = DecPpiObject(RawData.Filename)
    633         self.ProtocolObj = DecProtocolObject(RawData.Filename)
    634         self.ObjectDict = \
    635         {
    636             DT.TAB_GUIDS.upper()     :   self.GuidObj,
    637             DT.TAB_PPIS.upper()      :   self.PpiObj,
    638             DT.TAB_PROTOCOLS.upper() :   self.ProtocolObj
    639         }
    640     
    641     def GetDataObject(self):
    642         if self._RawData.CurrentScope:
    643             return self.ObjectDict[self._RawData.CurrentScope[0][0]]
    644         return None
    645     
    646     def GetGuidObject(self):
    647         return self.GuidObj
    648     
    649     def GetPpiObject(self):
    650         return self.PpiObj
    651     
    652     def GetProtocolObject(self):
    653         return self.ProtocolObj
    654     
    655     def _ParseItem(self):
    656         Line = self._RawData.CurrentLine
    657         TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1)
    658         if len(TokenList) < 2:
    659             self._LoggerError(ST.ERR_DECPARSE_CGUID)
    660         if TokenList[0] == '':
    661             self._LoggerError(ST.ERR_DECPARSE_CGUID_NAME)
    662         if TokenList[1] == '':
    663             self._LoggerError(ST.ERR_DECPARSE_CGUID_GUID)
    664         if not IsValidToken(CVAR_PATTERN, TokenList[0]):
    665             self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID)
    666         
    667         self._CheckReDefine(TokenList[0])
    668         
    669         if TokenList[1][0] != '{':
    670             if not CheckGuidRegFormat(TokenList[1]):
    671                 self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID)
    672             GuidString = TokenList[1]
    673         else:
    674             #

    675             # Convert C format GUID to GUID string and Simple error check

    676             #

    677             GuidString = GuidStructureStringToGuidString(TokenList[1])
    678             if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidString == '':
    679                 self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT)
    680     
    681             #

    682             # Check C format GUID

    683             #

    684             if not IsValidCFormatGuid(TokenList[1]):
    685                 self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT)
    686 
    687         Item = DecGuidItemObject(TokenList[0], TokenList[1], GuidString)
    688         ItemObject = self.ObjectDict[self._RawData.CurrentScope[0][0]]
    689         ItemObject.AddItem(Item, self._RawData.CurrentScope)
    690         return Item
    691 
    692 ## _DecUserExtension

    693 #

    694 # Parse user extention section

    695 #

    696 class _DecUserExtension(_DecBase):
    697     def __init__(self, RawData):
    698         _DecBase.__init__(self, RawData)
    699         self.ItemObject = DecUserExtensionObject(RawData.Filename)
    700         self._Headers = []
    701         self._CurItems = []
    702     
    703     def BlockStart(self):
    704         self._CurItems = []
    705         for Header in self._RawData.CurrentScope:
    706             if Header in self._Headers:
    707                 self._LoggerError(ST.ERR_DECPARSE_UE_DUPLICATE)
    708             else:
    709                 self._Headers.append(Header)
    710             
    711             for Item in self._CurItems:
    712                 if Item.UserId == Header[1] and Item.IdString == Header[2]:
    713                     Item.ArchAndModuleType.append(Header[3])
    714                     break
    715             else:
    716                 Item = DecUserExtensionItemObject()
    717                 Item.UserId = Header[1]
    718                 Item.IdString = Header[2]
    719                 Item.ArchAndModuleType.append(Header[3])
    720                 self._CurItems.append(Item)
    721                 self.ItemObject.AddItem(Item, None)
    722         self._LocalMacro = {}
    723     
    724     def _ParseItem(self):
    725         Line = self._RawData.CurrentLine
    726         Item = None
    727         for Item in self._CurItems:
    728             if Item.UserString:
    729                 Item.UserString = '\n'.join([Item.UserString, Line])
    730             else:
    731                 Item.UserString = Line
    732         return Item
    733 
    734 ## Dec

    735 #

    736 # Top dec parser

    737 #

    738 class Dec(_DecBase, _DecComments):    
    739     def __init__(self, DecFile, Parse = True):        
    740         try:
    741             Content = ConvertSpecialChar(open(DecFile, 'rb').readlines())
    742         except BaseException:
    743             Logger.Error(TOOL_NAME, FILE_OPEN_FAILURE, File=DecFile,
    744                          ExtraData=ST.ERR_DECPARSE_FILEOPEN % DecFile)
    745         RawData = FileContent(DecFile, Content)
    746         
    747         _DecComments.__init__(self)
    748         _DecBase.__init__(self, RawData)
    749         
    750         self.BinaryHeadComment = []
    751         self.PcdErrorCommentDict = {}
    752         
    753         self._Define    = _DecDefine(RawData)
    754         self._Include   = _DecInclude(RawData)
    755         self._Guid      = _DecGuid(RawData)
    756         self._LibClass  = _DecLibraryclass(RawData)
    757         self._Pcd       = _DecPcd(RawData)
    758         self._UserEx    = _DecUserExtension(RawData)
    759         
    760         #

    761         # DEC file supported data types (one type per section)

    762         #

    763         self._SectionParser = {
    764             DT.TAB_DEC_DEFINES.upper()                     :   self._Define,
    765             DT.TAB_INCLUDES.upper()                        :   self._Include,
    766             DT.TAB_LIBRARY_CLASSES.upper()                 :   self._LibClass,
    767             DT.TAB_GUIDS.upper()                           :   self._Guid,
    768             DT.TAB_PPIS.upper()                            :   self._Guid,
    769             DT.TAB_PROTOCOLS.upper()                       :   self._Guid,
    770             DT.TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   self._Pcd,
    771             DT.TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   self._Pcd,
    772             DT.TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   self._Pcd,
    773             DT.TAB_PCDS_DYNAMIC_NULL.upper()               :   self._Pcd,
    774             DT.TAB_PCDS_DYNAMIC_EX_NULL.upper()            :   self._Pcd,
    775             DT.TAB_USER_EXTENSIONS.upper()                 :   self._UserEx
    776         }
    777 
    778         if Parse:
    779             self.ParseDecComment()
    780             self.Parse()
    781             #

    782             # Parsing done, check required fields

    783             #

    784             self.CheckRequiredFields()
    785     
    786     def CheckRequiredFields(self):
    787         for SectionParser in self._SectionParser.values():
    788             if not SectionParser.CheckRequiredFields():
    789                 return False
    790         return True
    791 
    792     ##

    793     # Parse DEC file

    794     #

    795     def ParseDecComment(self):
    796         IsFileHeader = False
    797         IsBinaryHeader = False
    798         FileHeaderLineIndex = -1
    799         BinaryHeaderLineIndex = -1
    800         TokenSpaceGuidCName = ''
    801         
    802         #

    803         # Parse PCD error comment section

    804         #

    805         while not self._RawData.IsEndOfFile():
    806             self._RawData.CurrentLine = self._RawData.GetNextLine()
    807             if self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT) and \
    808                 DT.TAB_SECTION_START in self._RawData.CurrentLine and \
    809                 DT.TAB_SECTION_END in self._RawData.CurrentLine:
    810                 self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip()
    811 
    812                 if self._RawData.CurrentLine[0] == DT.TAB_SECTION_START and \
    813                     self._RawData.CurrentLine[-1] == DT.TAB_SECTION_END:
    814                     RawSection = self._RawData.CurrentLine[1:-1].strip()
    815                     if RawSection.upper().startswith(DT.TAB_PCD_ERROR.upper()+'.'):
    816                         TokenSpaceGuidCName = RawSection.split(DT.TAB_PCD_ERROR+'.')[1].strip()
    817                         continue
    818 
    819             if TokenSpaceGuidCName and self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT):
    820                 self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip()
    821                 if self._RawData.CurrentLine != '':
    822                     if DT.TAB_VALUE_SPLIT not in self._RawData.CurrentLine:
    823                         self._LoggerError(ST.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT)   
    824                           
    825                     PcdErrorNumber, PcdErrorMsg = GetSplitValueList(self._RawData.CurrentLine, DT.TAB_VALUE_SPLIT, 1)
    826                     PcdErrorNumber = ParsePcdErrorCode(PcdErrorNumber, self._RawData.Filename, self._RawData.LineIndex)
    827                     if not PcdErrorMsg.strip():
    828                         self._LoggerError(ST.ERR_DECPARSE_PCD_MISS_ERRORMSG)
    829                         
    830                     self.PcdErrorCommentDict[(TokenSpaceGuidCName, PcdErrorNumber)] = PcdErrorMsg.strip()
    831             else:
    832                 TokenSpaceGuidCName = ''
    833 
    834         self._RawData.LineIndex = 0
    835         self._RawData.CurrentLine = ''
    836         self._RawData.NextLine = ''
    837 
    838         while not self._RawData.IsEndOfFile():
    839             Line, Comment = CleanString(self._RawData.GetNextLine())
    840             
    841             #

    842             # Header must be pure comment

    843             #

    844             if Line != '':
    845                 self._RawData.UndoNextLine()
    846                 break
    847             
    848             if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) and Comment.find(DT.TAB_HEADER_COMMENT) > 0 \
    849                 and not Comment[2:Comment.find(DT.TAB_HEADER_COMMENT)].strip():
    850                 IsFileHeader = True
    851                 IsBinaryHeader = False
    852                 FileHeaderLineIndex = self._RawData.LineIndex
    853                 
    854             #

    855             # Get license information before '@file' 

    856             #   

    857             if not IsFileHeader and not IsBinaryHeader and Comment and Comment.startswith(DT.TAB_COMMENT_SPLIT) and \
    858             DT.TAB_BINARY_HEADER_COMMENT not in Comment:
    859                 self._HeadComment.append((Comment, self._RawData.LineIndex))
    860             
    861             if Comment and IsFileHeader and \
    862             not(Comment.startswith(DT.TAB_SPECIAL_COMMENT) \
    863             and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0):
    864                 self._HeadComment.append((Comment, self._RawData.LineIndex))
    865             #

    866             # Double '#' indicates end of header comments

    867             #

    868             if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsFileHeader:
    869                 IsFileHeader = False  
    870                 continue
    871             
    872             if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) \
    873             and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0:
    874                 IsBinaryHeader = True
    875                 IsFileHeader = False
    876                 BinaryHeaderLineIndex = self._RawData.LineIndex
    877                 
    878             if Comment and IsBinaryHeader:
    879                 self.BinaryHeadComment.append((Comment, self._RawData.LineIndex))
    880             #

    881             # Double '#' indicates end of header comments

    882             #

    883             if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsBinaryHeader:
    884                 IsBinaryHeader = False
    885                 break
    886             
    887             if FileHeaderLineIndex > -1 and not IsFileHeader and not IsBinaryHeader:
    888                 break
    889 
    890         if FileHeaderLineIndex > BinaryHeaderLineIndex and FileHeaderLineIndex > -1 and BinaryHeaderLineIndex > -1:
    891             self._LoggerError(ST.ERR_BINARY_HEADER_ORDER)
    892             
    893         if FileHeaderLineIndex == -1:
    894 #            self._LoggerError(ST.ERR_NO_SOURCE_HEADER)

    895             Logger.Error(TOOL_NAME, FORMAT_INVALID, 
    896                          ST.ERR_NO_SOURCE_HEADER,
    897                          File=self._RawData.Filename)
    898         return
    899     
    900     def _StopCurrentParsing(self, Line):
    901         return False
    902     
    903     def _ParseItem(self):
    904         self._SectionHeaderParser()
    905         if len(self._RawData.CurrentScope) == 0:
    906             self._LoggerError(ST.ERR_DECPARSE_SECTION_EMPTY)
    907         SectionObj = self._SectionParser[self._RawData.CurrentScope[0][0]]
    908         SectionObj.BlockStart()
    909         SectionObj.Parse()
    910         return SectionObj.GetDataObject()
    911 
    912     def _UserExtentionSectionParser(self):
    913         self._RawData.CurrentScope = []
    914         ArchList = set()
    915         Section = self._RawData.CurrentLine[1:-1]
    916         Par = ParserHelper(Section, self._RawData.Filename)
    917         while not Par.End():
    918             #

    919             # User extention

    920             #

    921             Token = Par.GetToken()
    922             if Token.upper() != DT.TAB_USER_EXTENSIONS.upper():
    923                 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE)
    924             UserExtension = Token.upper()
    925             Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)     
    926             
    927             #

    928             # UserID

    929             #

    930             Token = Par.GetToken()
    931             if not IsValidUserId(Token):
    932                 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_USERID)
    933             UserId = Token
    934             Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)
    935             #

    936             # IdString

    937             #

    938             Token = Par.GetToken()
    939             if not IsValidIdString(Token):
    940                 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_IDSTRING)
    941             IdString = Token
    942             Arch = 'COMMON'
    943             if Par.Expect(DT.TAB_SPLIT):
    944                 Token = Par.GetToken()
    945                 Arch = Token.upper()
    946                 if not IsValidArch(Arch):
    947                     self._LoggerError(ST.ERR_DECPARSE_ARCH)
    948             ArchList.add(Arch)
    949             if [UserExtension, UserId, IdString, Arch] not in \
    950                 self._RawData.CurrentScope:
    951                 self._RawData.CurrentScope.append(
    952                     [UserExtension, UserId, IdString, Arch]
    953                 )
    954             if not Par.Expect(DT.TAB_COMMA_SPLIT):
    955                 break
    956             elif Par.End():
    957                 self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMA)
    958         Par.AssertEnd(ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)
    959         if 'COMMON' in ArchList and len(ArchList) > 1:
    960             self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON)
    961  
    962     ## Section header parser

    963     #

    964     # The section header is always in following format:

    965     #

    966     # [section_name.arch<.platform|module_type>]

    967     #

    968     def _SectionHeaderParser(self):
    969         if self._RawData.CurrentLine[0] != DT.TAB_SECTION_START or self._RawData.CurrentLine[-1] != DT.TAB_SECTION_END:
    970             self._LoggerError(ST.ERR_DECPARSE_SECTION_IDENTIFY)
    971         
    972         RawSection = self._RawData.CurrentLine[1:-1].strip().upper()
    973         #

    974         # Check defines section which is only allowed to occur once and

    975         # no arch can be followed

    976         #

    977         if RawSection.startswith(DT.TAB_DEC_DEFINES.upper()):
    978             if RawSection != DT.TAB_DEC_DEFINES.upper():
    979                 self._LoggerError(ST.ERR_DECPARSE_DEFINE_SECNAME)
    980         #

    981         # Check user extension section

    982         #

    983         if RawSection.startswith(DT.TAB_USER_EXTENSIONS.upper()):
    984             return self._UserExtentionSectionParser()
    985         self._RawData.CurrentScope = []
    986         SectionNames = []
    987         ArchList = set()
    988         for Item in GetSplitValueList(RawSection, DT.TAB_COMMA_SPLIT):
    989             if Item == '':
    990                 self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine)
    991 
    992             ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
    993             #

    994             # different types of PCD are permissible in one section

    995             #

    996             SectionName = ItemList[0]
    997             if SectionName not in self._SectionParser:
    998                 self._LoggerError(ST.ERR_DECPARSE_SECTION_UNKNOW % SectionName)
    999             if SectionName not in SectionNames:
   1000                 SectionNames.append(SectionName)
   1001             #

   1002             # In DEC specification, all section headers have at most two part:

   1003             # SectionName.Arch except UserExtention

   1004             #

   1005             if len(ItemList) > 2:
   1006                 self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBTOOMANY % Item)
   1007 
   1008             if DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() in SectionNames and len(SectionNames) > 1:
   1009                 self._LoggerError(ST.ERR_DECPARSE_SECTION_FEATUREFLAG % DT.TAB_PCDS_FEATURE_FLAG_NULL) 
   1010             #

   1011             # S1 is always Arch

   1012             #

   1013             if len(ItemList) > 1:
   1014                 Str1 = ItemList[1]
   1015                 if not IsValidArch(Str1):
   1016                     self._LoggerError(ST.ERR_DECPARSE_ARCH)
   1017             else:
   1018                 Str1 = 'COMMON'
   1019             ArchList.add(Str1)
   1020 
   1021             if [SectionName, Str1] not in self._RawData.CurrentScope:
   1022                 self._RawData.CurrentScope.append([SectionName, Str1])
   1023         #

   1024         # 'COMMON' must not be used with specific ARCHs at the same section

   1025         #

   1026         if 'COMMON' in ArchList and len(ArchList) > 1:
   1027             self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON)
   1028         if len(SectionNames) == 0:
   1029             self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine)
   1030         if len(SectionNames) != 1:
   1031             for Sec in SectionNames:
   1032                 if not Sec.startswith(DT.TAB_PCDS.upper()):
   1033                     self._LoggerError(ST.ERR_DECPARSE_SECTION_NAME % str(SectionNames))
   1034     
   1035     def GetDefineSectionMacro(self):
   1036         return self._Define.GetLocalMacro()
   1037     def GetDefineSectionObject(self):
   1038         return self._Define.GetDataObject()
   1039     def GetIncludeSectionObject(self):
   1040         return self._Include.GetDataObject()
   1041     def GetGuidSectionObject(self):
   1042         return self._Guid.GetGuidObject()
   1043     def GetProtocolSectionObject(self):
   1044         return self._Guid.GetProtocolObject()
   1045     def GetPpiSectionObject(self):
   1046         return self._Guid.GetPpiObject()
   1047     def GetLibraryClassSectionObject(self):
   1048         return self._LibClass.GetDataObject()
   1049     def GetPcdSectionObject(self):
   1050         return self._Pcd.GetDataObject()
   1051     def GetUserExtensionSectionObject(self):
   1052         return self._UserEx.GetDataObject()
   1053     def GetPackageSpecification(self):
   1054         return self._Define.GetDataObject().GetPackageSpecification()   
   1055     def GetPackageName(self):
   1056         return self._Define.GetDataObject().GetPackageName()   
   1057     def GetPackageGuid(self):
   1058         return self._Define.GetDataObject().GetPackageGuid()    
   1059     def GetPackageVersion(self):
   1060         return self._Define.GetDataObject().GetPackageVersion()
   1061     def GetPackageUniFile(self):
   1062         return self._Define.GetDataObject().GetPackageUniFile()
   1063