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

      2 # This file is used to parse meta files

      3 #

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

      5 # (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>

      6 # This program and the accompanying materials

      7 # are licensed and made available under the terms and conditions of the BSD License

      8 # which accompanies this 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 
     15 ##

     16 # Import Modules

     17 #

     18 import Common.LongFilePathOs as os
     19 import re
     20 import time
     21 import copy
     22 
     23 import Common.EdkLogger as EdkLogger
     24 import Common.GlobalData as GlobalData
     25 
     26 from CommonDataClass.DataClass import *
     27 from Common.DataType import *
     28 from Common.String import *
     29 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression
     30 from Common.Expression import *
     31 from CommonDataClass.Exceptions import *
     32 from Common.LongFilePathSupport import OpenLongFilePath as open
     33 
     34 from MetaFileTable import MetaFileStorage
     35 from MetaFileCommentParser import CheckInfComment
     36 
     37 ## A decorator used to parse macro definition

     38 def ParseMacro(Parser):
     39     def MacroParser(self):
     40         Match = gMacroDefPattern.match(self._CurrentLine)
     41         if not Match:
     42             # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method

     43             Parser(self)
     44             return
     45 
     46         TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)
     47         # Syntax check

     48         if not TokenList[0]:
     49             EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
     50                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
     51         if len(TokenList) < 2:
     52             TokenList.append('')
     53 
     54         Type = Match.group(1)
     55         Name, Value = TokenList
     56         # Global macros can be only defined via environment variable

     57         if Name in GlobalData.gGlobalDefines:
     58             EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
     59                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
     60         # Only upper case letters, digit and '_' are allowed

     61         if not gMacroNamePattern.match(Name):
     62             EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
     63                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
     64 
     65         Value = ReplaceMacro(Value, self._Macros)
     66         if Type in self.DataType:
     67             self._ItemType = self.DataType[Type]
     68         else:
     69             self._ItemType = MODEL_META_DATA_DEFINE
     70         # DEFINE defined macros

     71         if Type == TAB_DSC_DEFINES_DEFINE:
     72             #

     73             # First judge whether this DEFINE is in conditional directive statements or not.

     74             #

     75             if type(self) == DscParser and self._InDirective > -1:
     76                 pass
     77             else:
     78                 if type(self) == DecParser:
     79                     if MODEL_META_DATA_HEADER in self._SectionType:
     80                         self._FileLocalMacros[Name] = Value
     81                     else:
     82                         self._ConstructSectionMacroDict(Name, Value)
     83                 elif self._SectionType == MODEL_META_DATA_HEADER:
     84                     self._FileLocalMacros[Name] = Value
     85                 else:
     86                     self._ConstructSectionMacroDict(Name, Value)
     87 
     88         # EDK_GLOBAL defined macros

     89         elif type(self) != DscParser:
     90             EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
     91                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
     92         elif self._SectionType != MODEL_META_DATA_HEADER:
     93             EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
     94                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
     95         elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
     96             EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
     97                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
     98 
     99         self._ValueList = [Type, Name, Value]
    100 
    101     return MacroParser
    102 
    103 ## Base class of parser

    104 #

    105 #  This class is used for derivation purpose. The specific parser for one kind

    106 # type file must derive this class and implement some public interfaces.

    107 #

    108 #   @param      FilePath        The path of platform description file

    109 #   @param      FileType        The raw data of DSC file

    110 #   @param      Table           Database used to retrieve module/package information

    111 #   @param      Macros          Macros used for replacement in file

    112 #   @param      Owner           Owner ID (for sub-section parsing)

    113 #   @param      From            ID from which the data comes (for !INCLUDE directive)

    114 #

    115 class MetaFileParser(object):
    116     # data type (file content) for specific file type

    117     DataType = {}
    118 
    119     # Parser objects used to implement singleton

    120     MetaFiles = {}
    121 
    122     ## Factory method

    123     #

    124     # One file, one parser object. This factory method makes sure that there's

    125     # only one object constructed for one meta file.

    126     #

    127     #   @param  Class           class object of real AutoGen class

    128     #                           (InfParser, DecParser or DscParser)

    129     #   @param  FilePath        The path of meta file

    130     #   @param  *args           The specific class related parameters

    131     #   @param  **kwargs        The specific class related dict parameters

    132     #

    133     def __new__(Class, FilePath, *args, **kwargs):
    134         if FilePath in Class.MetaFiles:
    135             return Class.MetaFiles[FilePath]
    136         else:
    137             ParserObject = super(MetaFileParser, Class).__new__(Class)
    138             Class.MetaFiles[FilePath] = ParserObject
    139             return ParserObject
    140 
    141     ## Constructor of MetaFileParser

    142     #

    143     #  Initialize object of MetaFileParser

    144     #

    145     #   @param      FilePath        The path of platform description file

    146     #   @param      FileType        The raw data of DSC file

    147     #   @param      Arch            Default Arch value for filtering sections

    148     #   @param      Table           Database used to retrieve module/package information

    149     #   @param      Owner           Owner ID (for sub-section parsing)

    150     #   @param      From            ID from which the data comes (for !INCLUDE directive)

    151     #

    152     def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
    153         self._Table = Table
    154         self._RawTable = Table
    155         self._Arch = Arch
    156         self._FileType = FileType
    157         self.MetaFile = FilePath
    158         self._FileDir = self.MetaFile.Dir
    159         self._Defines = {}
    160         self._FileLocalMacros = {}
    161         self._SectionsMacroDict = {}
    162 
    163         # for recursive parsing

    164         self._Owner = [Owner]
    165         self._From = From
    166 
    167         # parsr status for parsing

    168         self._ValueList = ['', '', '', '', '']
    169         self._Scope = []
    170         self._LineIndex = 0
    171         self._CurrentLine = ''
    172         self._SectionType = MODEL_UNKNOWN
    173         self._SectionName = ''
    174         self._InSubsection = False
    175         self._SubsectionType = MODEL_UNKNOWN
    176         self._SubsectionName = ''
    177         self._ItemType = MODEL_UNKNOWN
    178         self._LastItem = -1
    179         self._Enabled = 0
    180         self._Finished = False
    181         self._PostProcessed = False
    182         # Different version of meta-file has different way to parse.

    183         self._Version = 0
    184 
    185     ## Store the parsed data in table

    186     def _Store(self, *Args):
    187         return self._Table.Insert(*Args)
    188 
    189     ## Virtual method for starting parse

    190     def Start(self):
    191         raise NotImplementedError
    192 
    193     ## Notify a post-process is needed

    194     def DoPostProcess(self):
    195         self._PostProcessed = False
    196 
    197     ## Set parsing complete flag in both class and table

    198     def _Done(self):
    199         self._Finished = True
    200         ## Do not set end flag when processing included files

    201         if self._From == -1:
    202             self._Table.SetEndFlag()
    203 
    204     def _PostProcess(self):
    205         self._PostProcessed = True
    206 
    207     ## Get the parse complete flag

    208     def _GetFinished(self):
    209         return self._Finished
    210 
    211     ## Set the complete flag

    212     def _SetFinished(self, Value):
    213         self._Finished = Value
    214 
    215     ## Remove records that do not match given Filter Arch

    216     def _FilterRecordList(self, RecordList, FilterArch):
    217         NewRecordList = []
    218         for Record in RecordList:
    219             Arch = Record[3]
    220             if Arch == 'COMMON' or Arch == FilterArch:
    221                 NewRecordList.append(Record)
    222         return NewRecordList
    223 
    224     ## Use [] style to query data in table, just for readability

    225     #

    226     #   DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]

    227     #

    228     def __getitem__(self, DataInfo):
    229         if type(DataInfo) != type(()):
    230             DataInfo = (DataInfo,)
    231 
    232         # Parse the file first, if necessary

    233         if not self._Finished:
    234             if self._RawTable.IsIntegrity():
    235                 self._Finished = True
    236             else:
    237                 self._Table = self._RawTable
    238                 self._PostProcessed = False
    239                 self.Start()
    240 
    241         # No specific ARCH or Platform given, use raw data

    242         if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] == None):
    243             return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)
    244 
    245         # Do post-process if necessary

    246         if not self._PostProcessed:
    247             self._PostProcess()
    248 
    249         return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])
    250 
    251     ## Data parser for the common format in different type of file

    252     #

    253     #   The common format in the meatfile is like

    254     #

    255     #       xxx1 | xxx2 | xxx3

    256     #

    257     @ParseMacro
    258     def _CommonParser(self):
    259         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
    260         self._ValueList[0:len(TokenList)] = TokenList
    261 
    262     ## Data parser for the format in which there's path

    263     #

    264     #   Only path can have macro used. So we need to replace them before use.

    265     #

    266     @ParseMacro
    267     def _PathParser(self):
    268         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
    269         self._ValueList[0:len(TokenList)] = TokenList
    270         # Don't do macro replacement for dsc file at this point

    271         if type(self) != DscParser:
    272             Macros = self._Macros
    273             self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
    274 
    275     ## Skip unsupported data

    276     def _Skip(self):
    277         EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
    278                         Line=self._LineIndex + 1, ExtraData=self._CurrentLine);
    279         self._ValueList[0:1] = [self._CurrentLine]
    280 
    281     ## Skip unsupported data for UserExtension Section

    282     def _SkipUserExtension(self):
    283         self._ValueList[0:1] = [self._CurrentLine]
    284 
    285     ## Section header parser

    286     #

    287     #   The section header is always in following format:

    288     #

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

    290     #

    291     def _SectionHeaderParser(self):
    292         self._Scope = []
    293         self._SectionName = ''
    294         ArchList = set()
    295         for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
    296             if Item == '':
    297                 continue
    298             ItemList = GetSplitValueList(Item, TAB_SPLIT,2)
    299             # different section should not mix in one section

    300             if self._SectionName != '' and self._SectionName != ItemList[0].upper():
    301                 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
    302                                 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
    303             self._SectionName = ItemList[0].upper()
    304             if self._SectionName in self.DataType:
    305                 self._SectionType = self.DataType[self._SectionName]
    306                 # Check if the section name is valid

    307                 if self._SectionName not in SECTIONS_HAVE_ITEM_AFTER_ARCH and len(ItemList) > 3:
    308                     EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
    309                                     self.MetaFile, self._LineIndex + 1, self._CurrentLine)
    310             elif self._Version >= 0x00010005:
    311                 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
    312                                 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
    313             else:
    314                 self._SectionType = MODEL_UNKNOWN
    315 
    316             # S1 is always Arch

    317             if len(ItemList) > 1:
    318                 S1 = ItemList[1].upper()
    319             else:
    320                 S1 = 'COMMON'
    321             ArchList.add(S1)
    322 
    323             # S2 may be Platform or ModuleType

    324             if len(ItemList) > 2:
    325                 if self._SectionName.upper() in SECTIONS_HAVE_ITEM_PCD:
    326                     S2 = ItemList[2]
    327                 else:
    328                     S2 = ItemList[2].upper()
    329             else:
    330                 S2 = 'COMMON'
    331             self._Scope.append([S1, S2])
    332 
    333         # 'COMMON' must not be used with specific ARCHs at the same section

    334         if 'COMMON' in ArchList and len(ArchList) > 1:
    335             EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
    336                             File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
    337         # If the section information is needed later, it should be stored in database

    338         self._ValueList[0] = self._SectionName
    339 
    340     ## [defines] section parser

    341     @ParseMacro
    342     def _DefineParser(self):
    343         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
    344         self._ValueList[1:len(TokenList)] = TokenList
    345         if not self._ValueList[1]:
    346             EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
    347                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
    348         if not self._ValueList[2]:
    349             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
    350                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
    351 
    352         self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
    353         Name, Value = self._ValueList[1], self._ValueList[2]
    354         # Sometimes, we need to make differences between EDK and EDK2 modules 

    355         if Name == 'INF_VERSION':
    356             if re.match(r'0[xX][\da-f-A-F]{5,8}', Value):
    357                 self._Version = int(Value, 0)   
    358             elif re.match(r'\d+\.\d+', Value):
    359                 ValueList = Value.split('.')
    360                 Major = '%04o' % int(ValueList[0], 0)
    361                 Minor = '%04o' % int(ValueList[1], 0)
    362                 self._Version = int('0x' + Major + Minor, 0)
    363             else:
    364                 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
    365                                 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
    366 
    367         if type(self) == InfParser and self._Version < 0x00010005:
    368             # EDK module allows using defines as macros

    369             self._FileLocalMacros[Name] = Value
    370         self._Defines[Name] = Value
    371 
    372     ## [BuildOptions] section parser

    373     @ParseMacro
    374     def _BuildOptionParser(self):
    375         self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
    376         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
    377         TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
    378         if len(TokenList2) == 2:
    379             self._ValueList[0] = TokenList2[0]              # toolchain family

    380             self._ValueList[1] = TokenList2[1]              # keys

    381         else:
    382             self._ValueList[1] = TokenList[0]
    383         if len(TokenList) == 2 and type(self) != DscParser: # value

    384             self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
    385 
    386         if self._ValueList[1].count('_') != 4:
    387             EdkLogger.error(
    388                 'Parser',
    389                 FORMAT_INVALID,
    390                 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
    391                 ExtraData=self._CurrentLine,
    392                 File=self.MetaFile,
    393                 Line=self._LineIndex + 1
    394                 )
    395     def GetValidExpression(self, TokenSpaceGuid, PcdCName):
    396         return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)
    397     def _GetMacros(self):
    398         Macros = {}
    399         Macros.update(self._FileLocalMacros)
    400         Macros.update(self._GetApplicableSectionMacro())
    401         return Macros
    402 
    403     ## Construct section Macro dict 

    404     def _ConstructSectionMacroDict(self, Name, Value):
    405         ScopeKey = [(Scope[0], Scope[1]) for Scope in self._Scope]
    406         ScopeKey = tuple(ScopeKey)
    407         SectionDictKey = self._SectionType, ScopeKey
    408         #

    409         # DecParser SectionType is a list, will contain more than one item only in Pcd Section

    410         # As Pcd section macro usage is not alllowed, so here it is safe

    411         #

    412         if type(self) == DecParser:
    413             SectionDictKey = self._SectionType[0], ScopeKey
    414         if SectionDictKey not in self._SectionsMacroDict:
    415             self._SectionsMacroDict[SectionDictKey] = {}
    416         SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
    417         SectionLocalMacros[Name] = Value
    418 
    419     ## Get section Macros that are applicable to current line, which may come from other sections 

    420     ## that share the same name while scope is wider

    421     def _GetApplicableSectionMacro(self):
    422         Macros = {}
    423 
    424         ComComMacroDict = {}
    425         ComSpeMacroDict = {}
    426         SpeSpeMacroDict = {}
    427 
    428         ActiveSectionType = self._SectionType
    429         if type(self) == DecParser:
    430             ActiveSectionType = self._SectionType[0]
    431 
    432         for (SectionType, Scope) in self._SectionsMacroDict:
    433             if SectionType != ActiveSectionType:
    434                 continue
    435 
    436             for ActiveScope in self._Scope:
    437                 Scope0, Scope1 = ActiveScope[0], ActiveScope[1]
    438                 if(Scope0, Scope1) not in Scope:
    439                     break
    440             else:
    441                 SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
    442 
    443             for ActiveScope in self._Scope:
    444                 Scope0, Scope1 = ActiveScope[0], ActiveScope[1]
    445                 if(Scope0, Scope1) not in Scope and (Scope0, "COMMON") not in Scope and ("COMMON", Scope1) not in Scope:
    446                     break
    447             else:
    448                 ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
    449 
    450             if ("COMMON", "COMMON") in Scope:
    451                 ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
    452 
    453         Macros.update(ComComMacroDict)
    454         Macros.update(ComSpeMacroDict)
    455         Macros.update(SpeSpeMacroDict)
    456 
    457         return Macros
    458 
    459     _SectionParser = {}
    460     Finished = property(_GetFinished, _SetFinished)
    461     _Macros = property(_GetMacros)
    462 
    463 
    464 ## INF file parser class

    465 #

    466 #   @param      FilePath        The path of platform description file

    467 #   @param      FileType        The raw data of DSC file

    468 #   @param      Table           Database used to retrieve module/package information

    469 #   @param      Macros          Macros used for replacement in file

    470 #

    471 class InfParser(MetaFileParser):
    472     # INF file supported data types (one type per section)

    473     DataType = {
    474         TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
    475         TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
    476         TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
    477         TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
    478         TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
    479         TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
    480         TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
    481         TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
    482         TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
    483         TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
    484         TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
    485         TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
    486         TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
    487         TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
    488         TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
    489         TAB_GUIDS.upper() : MODEL_EFI_GUID,
    490         TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
    491         TAB_PPIS.upper() : MODEL_EFI_PPI,
    492         TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
    493         TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
    494         TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
    495     }
    496 
    497     ## Constructor of InfParser

    498     #

    499     #  Initialize object of InfParser

    500     #

    501     #   @param      FilePath        The path of module description file

    502     #   @param      FileType        The raw data of DSC file

    503     #   @param      Arch            Default Arch value for filtering sections

    504     #   @param      Table           Database used to retrieve module/package information

    505     #

    506     def __init__(self, FilePath, FileType, Arch, Table):
    507         # prevent re-initialization

    508         if hasattr(self, "_Table"):
    509             return
    510         MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)
    511         self.PcdsDict = {}
    512 
    513     ## Parser starter

    514     def Start(self):
    515         NmakeLine = ''
    516         Content = ''
    517         try:
    518             Content = open(str(self.MetaFile), 'r').readlines()
    519         except:
    520             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
    521 
    522         # parse the file line by line

    523         IsFindBlockComment = False
    524         GetHeaderComment = False
    525         TailComments = []
    526         SectionComments = []
    527         Comments = []
    528 
    529         for Index in range(0, len(Content)):
    530             # skip empty, commented, block commented lines

    531             Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)
    532             NextLine = ''
    533             if Index + 1 < len(Content):
    534                 NextLine, NextComment = CleanString2(Content[Index + 1])
    535             if Line == '':
    536                 if Comment:
    537                     Comments.append((Comment, Index + 1))
    538                 elif GetHeaderComment:
    539                     SectionComments.extend(Comments)
    540                     Comments = []
    541                 continue
    542             if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:
    543                 IsFindBlockComment = True
    544                 continue
    545             if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:
    546                 IsFindBlockComment = False
    547                 continue
    548             if IsFindBlockComment:
    549                 continue
    550 
    551             self._LineIndex = Index
    552             self._CurrentLine = Line
    553 
    554             # section header

    555             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
    556                 if not GetHeaderComment:
    557                     for Cmt, LNo in Comments:
    558                         self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', 'COMMON',
    559                                     'COMMON', self._Owner[-1], LNo, -1, LNo, -1, 0)
    560                     GetHeaderComment = True
    561                 else:
    562                     TailComments.extend(SectionComments + Comments)
    563                 Comments = []
    564                 self._SectionHeaderParser()
    565                 # Check invalid sections

    566                 if self._Version < 0x00010005:
    567                     if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
    568                                              MODEL_EFI_LIBRARY_CLASS,
    569                                              MODEL_META_DATA_PACKAGE,
    570                                              MODEL_PCD_FIXED_AT_BUILD,
    571                                              MODEL_PCD_PATCHABLE_IN_MODULE,
    572                                              MODEL_PCD_FEATURE_FLAG,
    573                                              MODEL_PCD_DYNAMIC_EX,
    574                                              MODEL_PCD_DYNAMIC,
    575                                              MODEL_EFI_GUID,
    576                                              MODEL_EFI_PROTOCOL,
    577                                              MODEL_EFI_PPI,
    578                                              MODEL_META_DATA_USER_EXTENSION]:
    579                         EdkLogger.error('Parser', FORMAT_INVALID,
    580                                         "Section [%s] is not allowed in inf file without version" % (self._SectionName),
    581                                         ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
    582                 elif self._SectionType in [MODEL_EFI_INCLUDE,
    583                                            MODEL_EFI_LIBRARY_INSTANCE,
    584                                            MODEL_META_DATA_NMAKE]:
    585                     EdkLogger.error('Parser', FORMAT_INVALID,
    586                                     "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
    587                                     ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
    588                 continue
    589             # merge two lines specified by '\' in section NMAKE

    590             elif self._SectionType == MODEL_META_DATA_NMAKE:
    591                 if Line[-1] == '\\':
    592                     if NextLine == '':
    593                         self._CurrentLine = NmakeLine + Line[0:-1]
    594                         NmakeLine = ''
    595                     else:
    596                         if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
    597                             self._CurrentLine = NmakeLine + Line[0:-1]
    598                             NmakeLine = ''
    599                         else:
    600                             NmakeLine = NmakeLine + ' ' + Line[0:-1]
    601                             continue
    602                 else:
    603                     self._CurrentLine = NmakeLine + Line
    604                     NmakeLine = ''
    605 
    606             # section content
    607             self._ValueList = ['', '', '']
    608             # parse current line, result will be put in self._ValueList
    609             self._SectionParser[self._SectionType](self)
    610             if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
    611                 self._ItemType = -1
    612                 Comments = []
    613                 continue
    614             if Comment:
    615                 Comments.append((Comment, Index + 1))
    616             if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:
    617                 CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)
    618             #
    619             # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
    620             # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
    621             #
    622             for Arch, Platform in self._Scope:
    623                 LastItem = self._Store(self._SectionType,
    624                             self._ValueList[0],
    625                             self._ValueList[1],
    626                             self._ValueList[2],
    627                             Arch,
    628                             Platform,
    629                             self._Owner[-1],
    630                             self._LineIndex + 1,
    631                             - 1,
    632                             self._LineIndex + 1,
    633                             - 1,
    634                             0
    635                             )
    636                 for Comment, LineNo in Comments:
    637                     self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,
    638                                 LastItem, LineNo, -1, LineNo, -1, 0)
    639             Comments = []
    640             SectionComments = []
    641         TailComments.extend(SectionComments + Comments)
    642         if IsFindBlockComment:
    643             EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
    644                             File=self.MetaFile)
    645 
    646         # If there are tail comments in INF file, save to database whatever the comments are
    647         for Comment in TailComments:
    648             self._Store(MODEL_META_DATA_TAIL_COMMENT, Comment[0], '', '', 'COMMON',
    649                                 'COMMON', self._Owner[-1], -1, -1, -1, -1, 0)
    650         self._Done()
    651 
    652     ## Data parser for the format in which there's path
    653     #

    654     #   Only path can have macro used. So we need to replace them before use.

    655     #

    656     def _IncludeParser(self):
    657         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
    658         self._ValueList[0:len(TokenList)] = TokenList
    659         Macros = self._Macros
    660         if Macros:
    661             for Index in range(0, len(self._ValueList)):
    662                 Value = self._ValueList[Index]
    663                 if not Value:
    664                     continue
    665 
    666                 if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
    667                     Value = '$(EDK_SOURCE)' + Value[17:]
    668                 if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:
    669                     pass
    670                 elif Value.startswith('.'):
    671                     pass
    672                 elif Value.startswith('$('):
    673                     pass
    674                 else:
    675                     Value = '$(EFI_SOURCE)/' + Value
    676 
    677                 self._ValueList[Index] = ReplaceMacro(Value, Macros)
    678 
    679     ## Parse [Sources] section

    680     #

    681     #   Only path can have macro used. So we need to replace them before use.

    682     #

    683     @ParseMacro
    684     def _SourceFileParser(self):
    685         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
    686         self._ValueList[0:len(TokenList)] = TokenList
    687         Macros = self._Macros
    688         # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'

    689         if 'COMPONENT_TYPE' in Macros:
    690             if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
    691                 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
    692         if self._Defines['BASE_NAME'] == 'Microcode':
    693             pass
    694         self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
    695 
    696     ## Parse [Binaries] section

    697     #

    698     #   Only path can have macro used. So we need to replace them before use.

    699     #

    700     @ParseMacro
    701     def _BinaryFileParser(self):
    702         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
    703         if len(TokenList) < 2:
    704             EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
    705                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
    706                             File=self.MetaFile, Line=self._LineIndex + 1)
    707         if not TokenList[0]:
    708             EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
    709                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
    710                             File=self.MetaFile, Line=self._LineIndex + 1)
    711         if not TokenList[1]:
    712             EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
    713                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
    714                             File=self.MetaFile, Line=self._LineIndex + 1)
    715         self._ValueList[0:len(TokenList)] = TokenList
    716         self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
    717 
    718     ## [nmake] section parser (Edk.x style only)

    719     def _NmakeParser(self):
    720         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
    721         self._ValueList[0:len(TokenList)] = TokenList
    722         # remove macros

    723         self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
    724         # remove self-reference in macro setting

    725         #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})

    726 
    727     ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser

    728     @ParseMacro
    729     def _PcdParser(self):
    730         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
    731         ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
    732         if len(ValueList) != 2:
    733             EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
    734                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
    735                             File=self.MetaFile, Line=self._LineIndex + 1)
    736         self._ValueList[0:1] = ValueList
    737         if len(TokenList) > 1:
    738             self._ValueList[2] = TokenList[1]
    739         if self._ValueList[0] == '' or self._ValueList[1] == '':
    740             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
    741                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
    742                             File=self.MetaFile, Line=self._LineIndex + 1)
    743 
    744         # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.

    745         if self._ValueList[2] != '':
    746             InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
    747             if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
    748                 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
    749             elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
    750                 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
    751         if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:
    752             self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType
    753         elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:
    754             EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",
    755                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
    756                             File=self.MetaFile, Line=self._LineIndex + 1)
    757 
    758     ## [depex] section parser

    759     @ParseMacro
    760     def _DepexParser(self):
    761         self._ValueList[0:1] = [self._CurrentLine]
    762 
    763     _SectionParser = {
    764         MODEL_UNKNOWN                   :   MetaFileParser._Skip,
    765         MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,
    766         MODEL_META_DATA_BUILD_OPTION    :   MetaFileParser._BuildOptionParser,
    767         MODEL_EFI_INCLUDE               :   _IncludeParser, # for Edk.x modules

    768         MODEL_EFI_LIBRARY_INSTANCE      :   MetaFileParser._CommonParser, # for Edk.x modules

    769         MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,
    770         MODEL_META_DATA_PACKAGE         :   MetaFileParser._PathParser,
    771         MODEL_META_DATA_NMAKE           :   _NmakeParser, # for Edk.x modules

    772         MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,
    773         MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,
    774         MODEL_PCD_FEATURE_FLAG          :   _PcdParser,
    775         MODEL_PCD_DYNAMIC_EX            :   _PcdParser,
    776         MODEL_PCD_DYNAMIC               :   _PcdParser,
    777         MODEL_EFI_SOURCE_FILE           :   _SourceFileParser,
    778         MODEL_EFI_GUID                  :   MetaFileParser._CommonParser,
    779         MODEL_EFI_PROTOCOL              :   MetaFileParser._CommonParser,
    780         MODEL_EFI_PPI                   :   MetaFileParser._CommonParser,
    781         MODEL_EFI_DEPEX                 :   _DepexParser,
    782         MODEL_EFI_BINARY_FILE           :   _BinaryFileParser,
    783         MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._SkipUserExtension,
    784     }
    785 
    786 ## DSC file parser class

    787 #

    788 #   @param      FilePath        The path of platform description file

    789 #   @param      FileType        The raw data of DSC file

    790 #   @param      Table           Database used to retrieve module/package information

    791 #   @param      Macros          Macros used for replacement in file

    792 #   @param      Owner           Owner ID (for sub-section parsing)

    793 #   @param      From            ID from which the data comes (for !INCLUDE directive)

    794 #

    795 class DscParser(MetaFileParser):
    796     # DSC file supported data types (one type per section)

    797     DataType = {
    798         TAB_SKUIDS.upper()                          :   MODEL_EFI_SKU_ID,
    799         TAB_LIBRARIES.upper()                       :   MODEL_EFI_LIBRARY_INSTANCE,
    800         TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,
    801         TAB_BUILD_OPTIONS.upper()                   :   MODEL_META_DATA_BUILD_OPTION,
    802         TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,
    803         TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,
    804         TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,
    805         TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper()       :   MODEL_PCD_DYNAMIC_DEFAULT,
    806         TAB_PCDS_DYNAMIC_HII_NULL.upper()           :   MODEL_PCD_DYNAMIC_HII,
    807         TAB_PCDS_DYNAMIC_VPD_NULL.upper()           :   MODEL_PCD_DYNAMIC_VPD,
    808         TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper()    :   MODEL_PCD_DYNAMIC_EX_DEFAULT,
    809         TAB_PCDS_DYNAMIC_EX_HII_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_HII,
    810         TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_VPD,
    811         TAB_COMPONENTS.upper()                      :   MODEL_META_DATA_COMPONENT,
    812         TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() :   MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
    813         TAB_DSC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,
    814         TAB_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,
    815         TAB_DSC_DEFINES_EDKGLOBAL                   :   MODEL_META_DATA_GLOBAL_DEFINE,
    816         TAB_INCLUDE.upper()                         :   MODEL_META_DATA_INCLUDE,
    817         TAB_IF.upper()                              :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
    818         TAB_IF_DEF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
    819         TAB_IF_N_DEF.upper()                        :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
    820         TAB_ELSE_IF.upper()                         :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
    821         TAB_ELSE.upper()                            :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
    822         TAB_END_IF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
    823         TAB_USER_EXTENSIONS.upper()                 :   MODEL_META_DATA_USER_EXTENSION,
    824     }
    825 
    826     # Valid names in define section

    827     DefineKeywords = [
    828         "DSC_SPECIFICATION",
    829         "PLATFORM_NAME",
    830         "PLATFORM_GUID",
    831         "PLATFORM_VERSION",
    832         "SKUID_IDENTIFIER",
    833         "PCD_INFO_GENERATION",
    834         "PCD_VAR_CHECK_GENERATION",
    835         "SUPPORTED_ARCHITECTURES",
    836         "BUILD_TARGETS",
    837         "OUTPUT_DIRECTORY",
    838         "FLASH_DEFINITION",
    839         "BUILD_NUMBER",
    840         "RFC_LANGUAGES",
    841         "ISO_LANGUAGES",
    842         "TIME_STAMP_FILE",
    843         "VPD_TOOL_GUID",
    844         "FIX_LOAD_TOP_MEMORY_ADDRESS",
    845         "PREBUILD",
    846         "POSTBUILD"
    847     ]
    848 
    849     SubSectionDefineKeywords = [
    850         "FILE_GUID"
    851     ]
    852 
    853     SymbolPattern = ValueExpression.SymbolPattern
    854 
    855     ## Constructor of DscParser

    856     #

    857     #  Initialize object of DscParser

    858     #

    859     #   @param      FilePath        The path of platform description file

    860     #   @param      FileType        The raw data of DSC file

    861     #   @param      Arch            Default Arch value for filtering sections

    862     #   @param      Table           Database used to retrieve module/package information

    863     #   @param      Owner           Owner ID (for sub-section parsing)

    864     #   @param      From            ID from which the data comes (for !INCLUDE directive)

    865     #

    866     def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
    867         # prevent re-initialization

    868         if hasattr(self, "_Table"):
    869             return
    870         MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)
    871         self._Version = 0x00010005  # Only EDK2 dsc file is supported

    872         # to store conditional directive evaluation result

    873         self._DirectiveStack = []
    874         self._DirectiveEvalStack = []
    875         self._Enabled = 1
    876 
    877         #

    878         # Specify whether current line is in uncertain condition

    879         #

    880         self._InDirective = -1
    881 
    882         # Final valid replacable symbols

    883         self._Symbols = {}
    884         #

    885         #  Map the ID between the original table and new table to track

    886         #  the owner item

    887         #

    888         self._IdMapping = {-1:-1}
    889 
    890     ## Parser starter

    891     def Start(self):
    892         Content = ''
    893         try:
    894             Content = open(str(self.MetaFile), 'r').readlines()
    895         except:
    896             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
    897 
    898         OwnerId = {}
    899         for Index in range(0, len(Content)):
    900             Line = CleanString(Content[Index])
    901             # skip empty line

    902             if Line == '':
    903                 continue
    904 
    905             self._CurrentLine = Line
    906             self._LineIndex = Index
    907             if self._InSubsection and self._Owner[-1] == -1:
    908                 self._Owner.append(self._LastItem)
    909 
    910             # section header

    911             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
    912                 self._SectionType = MODEL_META_DATA_SECTION_HEADER
    913             # subsection ending

    914             elif Line[0] == '}' and self._InSubsection:
    915                 self._InSubsection = False
    916                 self._SubsectionType = MODEL_UNKNOWN
    917                 self._SubsectionName = ''
    918                 self._Owner[-1] = -1
    919                 OwnerId = {}
    920                 continue
    921             # subsection header

    922             elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
    923                 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
    924             # directive line

    925             elif Line[0] == '!':
    926                 self._DirectiveParser()
    927                 continue
    928             if Line[0] == TAB_OPTION_START and not self._InSubsection:
    929                 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1),ExtraData=self.MetaFile)
    930 
    931             if self._InSubsection:
    932                 SectionType = self._SubsectionType
    933             else:
    934                 SectionType = self._SectionType
    935             self._ItemType = SectionType
    936 
    937             self._ValueList = ['', '', '']
    938             self._SectionParser[SectionType](self)
    939             if self._ValueList == None:
    940                 continue
    941             #

    942             # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,

    943             # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1

    944             #

    945             for Arch, ModuleType in self._Scope:
    946                 Owner = self._Owner[-1]
    947                 if self._SubsectionType != MODEL_UNKNOWN:
    948                     Owner = OwnerId[Arch]
    949                 self._LastItem = self._Store(
    950                                         self._ItemType,
    951                                         self._ValueList[0],
    952                                         self._ValueList[1],
    953                                         self._ValueList[2],
    954                                         Arch,
    955                                         ModuleType,
    956                                         Owner,
    957                                         self._From,
    958                                         self._LineIndex + 1,
    959                                         - 1,
    960                                         self._LineIndex + 1,
    961                                         - 1,
    962                                         self._Enabled
    963                                         )
    964                 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
    965                     OwnerId[Arch] = self._LastItem
    966 
    967         if self._DirectiveStack:
    968             Type, Line, Text = self._DirectiveStack[-1]
    969             EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
    970                             ExtraData=Text, File=self.MetaFile, Line=Line)
    971         self._Done()
    972 
    973     ## <subsection_header> parser

    974     def _SubsectionHeaderParser(self):
    975         self._SubsectionName = self._CurrentLine[1:-1].upper()
    976         if self._SubsectionName in self.DataType:
    977             self._SubsectionType = self.DataType[self._SubsectionName]
    978         else:
    979             self._SubsectionType = MODEL_UNKNOWN
    980             EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
    981                            Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
    982         self._ValueList[0] = self._SubsectionName
    983 
    984     ## Directive statement parser

    985     def _DirectiveParser(self):
    986         self._ValueList = ['', '', '']
    987         TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
    988         self._ValueList[0:len(TokenList)] = TokenList
    989 
    990         # Syntax check

    991         DirectiveName = self._ValueList[0].upper()
    992         if DirectiveName not in self.DataType:
    993             EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
    994                             File=self.MetaFile, Line=self._LineIndex + 1)
    995 
    996         if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
    997             self._InDirective += 1
    998 
    999         if DirectiveName in ['!ENDIF']:
   1000             self._InDirective -= 1
   1001 
   1002         if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
   1003             EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
   1004                             File=self.MetaFile, Line=self._LineIndex + 1,
   1005                             ExtraData=self._CurrentLine)
   1006 
   1007         ItemType = self.DataType[DirectiveName]
   1008         Scope = [['COMMON', 'COMMON']]
   1009         if ItemType == MODEL_META_DATA_INCLUDE:
   1010             Scope = self._Scope
   1011         if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
   1012             # Remove all directives between !if and !endif, including themselves

   1013             while self._DirectiveStack:
   1014                 # Remove any !else or !elseif

   1015                 DirectiveInfo = self._DirectiveStack.pop()
   1016                 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
   1017                                         MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
   1018                                         MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
   1019                     break
   1020             else:
   1021                 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
   1022                                 File=self.MetaFile, Line=self._LineIndex + 1,
   1023                                 ExtraData=self._CurrentLine)
   1024         elif ItemType != MODEL_META_DATA_INCLUDE:
   1025             # Break if there's a !else is followed by a !elseif

   1026             if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
   1027                self._DirectiveStack and \
   1028                self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
   1029                 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
   1030                                 File=self.MetaFile, Line=self._LineIndex + 1,
   1031                                 ExtraData=self._CurrentLine)
   1032             self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
   1033 
   1034         #

   1035         # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,

   1036         # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1

   1037         #

   1038         for Arch, ModuleType in Scope:
   1039             self._LastItem = self._Store(
   1040                                     ItemType,
   1041                                     self._ValueList[0],
   1042                                     self._ValueList[1],
   1043                                     self._ValueList[2],
   1044                                     Arch,
   1045                                     ModuleType,
   1046                                     self._Owner[-1],
   1047                                     self._From,
   1048                                     self._LineIndex + 1,
   1049                                     - 1,
   1050                                     self._LineIndex + 1,
   1051                                     - 1,
   1052                                     0
   1053                                     )
   1054 
   1055     ## [defines] section parser

   1056     @ParseMacro
   1057     def _DefineParser(self):
   1058         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
   1059         self._ValueList[1:len(TokenList)] = TokenList
   1060 
   1061         # Syntax check

   1062         if not self._ValueList[1]:
   1063             EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
   1064                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
   1065         if not self._ValueList[2]:
   1066             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
   1067                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
   1068         if (not self._ValueList[1] in self.DefineKeywords and
   1069             (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):
   1070             EdkLogger.error('Parser', FORMAT_INVALID,
   1071                             "Unknown keyword found: %s. "
   1072                             "If this is a macro you must "
   1073                             "add it as a DEFINE in the DSC" % self._ValueList[1],
   1074                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
   1075         if not self._InSubsection:
   1076             self._Defines[self._ValueList[1]] = self._ValueList[2]
   1077         self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
   1078 
   1079     @ParseMacro
   1080     def _SkuIdParser(self):
   1081         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
   1082         if len(TokenList) != 2:
   1083             EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",
   1084                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
   1085         self._ValueList[0:len(TokenList)] = TokenList
   1086 
   1087     ## Parse Edk style of library modules

   1088     @ParseMacro
   1089     def _LibraryInstanceParser(self):
   1090         self._ValueList[0] = self._CurrentLine
   1091 
   1092     ## PCD sections parser

   1093     #

   1094     #   [PcdsFixedAtBuild]

   1095     #   [PcdsPatchableInModule]

   1096     #   [PcdsFeatureFlag]

   1097     #   [PcdsDynamicEx

   1098     #   [PcdsDynamicExDefault]

   1099     #   [PcdsDynamicExVpd]

   1100     #   [PcdsDynamicExHii]

   1101     #   [PcdsDynamic]

   1102     #   [PcdsDynamicDefault]

   1103     #   [PcdsDynamicVpd]

   1104     #   [PcdsDynamicHii]

   1105     #

   1106     @ParseMacro
   1107     def _PcdParser(self):
   1108         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
   1109         self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
   1110         if len(TokenList) == 2:
   1111             self._ValueList[2] = TokenList[1]
   1112         if self._ValueList[0] == '' or self._ValueList[1] == '':
   1113             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
   1114                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
   1115                             File=self.MetaFile, Line=self._LineIndex + 1)
   1116         if self._ValueList[2] == '':
   1117             #

   1118             # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE

   1119             #

   1120             if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
   1121                 return
   1122             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
   1123                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
   1124                             File=self.MetaFile, Line=self._LineIndex + 1)
   1125 
   1126         # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD

   1127         ValueList = GetSplitValueList(self._ValueList[2])
   1128         if len(ValueList) > 1 and ValueList[1] != TAB_VOID \
   1129                               and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
   1130             EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
   1131                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
   1132 
   1133         # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.

   1134         DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
   1135         if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
   1136             self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
   1137         elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
   1138             self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
   1139 
   1140 
   1141     ## [components] section parser

   1142     @ParseMacro
   1143     def _ComponentParser(self):
   1144         if self._CurrentLine[-1] == '{':
   1145             self._ValueList[0] = self._CurrentLine[0:-1].strip()
   1146             self._InSubsection = True
   1147         else:
   1148             self._ValueList[0] = self._CurrentLine
   1149 
   1150     ## [LibraryClasses] section

   1151     @ParseMacro
   1152     def _LibraryClassParser(self):
   1153         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
   1154         if len(TokenList) < 2:
   1155             EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
   1156                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
   1157                             File=self.MetaFile, Line=self._LineIndex + 1)
   1158         if TokenList[0] == '':
   1159             EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
   1160                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
   1161                             File=self.MetaFile, Line=self._LineIndex + 1)
   1162         if TokenList[1] == '':
   1163             EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
   1164                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
   1165                             File=self.MetaFile, Line=self._LineIndex + 1)
   1166 
   1167         self._ValueList[0:len(TokenList)] = TokenList
   1168 
   1169     def _CompponentSourceOverridePathParser(self):
   1170         self._ValueList[0] = self._CurrentLine
   1171 
   1172     ## [BuildOptions] section parser

   1173     @ParseMacro
   1174     def _BuildOptionParser(self):
   1175         self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
   1176         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
   1177         TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
   1178         if len(TokenList2) == 2:
   1179             self._ValueList[0] = TokenList2[0]  # toolchain family

   1180             self._ValueList[1] = TokenList2[1]  # keys

   1181         else:
   1182             self._ValueList[1] = TokenList[0]
   1183         if len(TokenList) == 2:                 # value

   1184             self._ValueList[2] = TokenList[1]
   1185 
   1186         if self._ValueList[1].count('_') != 4:
   1187             EdkLogger.error(
   1188                 'Parser',
   1189                 FORMAT_INVALID,
   1190                 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
   1191                 ExtraData=self._CurrentLine,
   1192                 File=self.MetaFile,
   1193                 Line=self._LineIndex + 1
   1194                 )
   1195 
   1196     ## Override parent's method since we'll do all macro replacements in parser

   1197     def _GetMacros(self):
   1198         Macros = {}
   1199         Macros.update(self._FileLocalMacros)
   1200         Macros.update(self._GetApplicableSectionMacro())
   1201         Macros.update(GlobalData.gEdkGlobal)
   1202         Macros.update(GlobalData.gPlatformDefines)
   1203         Macros.update(GlobalData.gCommandLineDefines)
   1204         # PCD cannot be referenced in macro definition

   1205         if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
   1206             Macros.update(self._Symbols)
   1207         return Macros
   1208 
   1209     def _PostProcess(self):
   1210         Processer = {
   1211             MODEL_META_DATA_SECTION_HEADER                  :   self.__ProcessSectionHeader,
   1212             MODEL_META_DATA_SUBSECTION_HEADER               :   self.__ProcessSubsectionHeader,
   1213             MODEL_META_DATA_HEADER                          :   self.__ProcessDefine,
   1214             MODEL_META_DATA_DEFINE                          :   self.__ProcessDefine,
   1215             MODEL_META_DATA_GLOBAL_DEFINE                   :   self.__ProcessDefine,
   1216             MODEL_META_DATA_INCLUDE                         :   self.__ProcessDirective,
   1217             MODEL_META_DATA_CONDITIONAL_STATEMENT_IF        :   self.__ProcessDirective,
   1218             MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE      :   self.__ProcessDirective,
   1219             MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF     :   self.__ProcessDirective,
   1220             MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF    :   self.__ProcessDirective,
   1221             MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF     :   self.__ProcessDirective,
   1222             MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF    :   self.__ProcessDirective,
   1223             MODEL_EFI_SKU_ID                                :   self.__ProcessSkuId,
   1224             MODEL_EFI_LIBRARY_INSTANCE                      :   self.__ProcessLibraryInstance,
   1225             MODEL_EFI_LIBRARY_CLASS                         :   self.__ProcessLibraryClass,
   1226             MODEL_PCD_FIXED_AT_BUILD                        :   self.__ProcessPcd,
   1227             MODEL_PCD_PATCHABLE_IN_MODULE                   :   self.__ProcessPcd,
   1228             MODEL_PCD_FEATURE_FLAG                          :   self.__ProcessPcd,
   1229             MODEL_PCD_DYNAMIC_DEFAULT                       :   self.__ProcessPcd,
   1230             MODEL_PCD_DYNAMIC_HII                           :   self.__ProcessPcd,
   1231             MODEL_PCD_DYNAMIC_VPD                           :   self.__ProcessPcd,
   1232             MODEL_PCD_DYNAMIC_EX_DEFAULT                    :   self.__ProcessPcd,
   1233             MODEL_PCD_DYNAMIC_EX_HII                        :   self.__ProcessPcd,
   1234             MODEL_PCD_DYNAMIC_EX_VPD                        :   self.__ProcessPcd,
   1235             MODEL_META_DATA_COMPONENT                       :   self.__ProcessComponent,
   1236             MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH  :   self.__ProcessSourceOverridePath,
   1237             MODEL_META_DATA_BUILD_OPTION                    :   self.__ProcessBuildOption,
   1238             MODEL_UNKNOWN                                   :   self._Skip,
   1239             MODEL_META_DATA_USER_EXTENSION                  :   self._SkipUserExtension,
   1240         }
   1241 
   1242         self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)
   1243         self._Table.Create()
   1244         self._DirectiveStack = []
   1245         self._DirectiveEvalStack = []
   1246         self._FileWithError = self.MetaFile
   1247         self._FileLocalMacros = {}
   1248         self._SectionsMacroDict = {}
   1249         GlobalData.gPlatformDefines = {}
   1250 
   1251         # Get all macro and PCD which has straitforward value

   1252         self.__RetrievePcdValue()
   1253         self._Content = self._RawTable.GetAll()
   1254         self._ContentIndex = 0
   1255         self._InSubsection = False
   1256         while self._ContentIndex < len(self._Content) :
   1257             Id, self._ItemType, V1, V2, V3, S1, S2, Owner, self._From, \
   1258                 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
   1259 
   1260             if self._From < 0:
   1261                 self._FileWithError = self.MetaFile
   1262 
   1263             self._ContentIndex += 1
   1264 
   1265             self._Scope = [[S1, S2]]
   1266             #

   1267             # For !include directive, handle it specially,

   1268             # merge arch and module type in case of duplicate items

   1269             #

   1270             while self._ItemType == MODEL_META_DATA_INCLUDE:
   1271                 if self._ContentIndex >= len(self._Content):
   1272                     break
   1273                 Record = self._Content[self._ContentIndex]
   1274                 if LineStart == Record[9] and LineEnd == Record[11]:
   1275                     if [Record[5], Record[6]] not in self._Scope:
   1276                         self._Scope.append([Record[5], Record[6]])
   1277                     self._ContentIndex += 1
   1278                 else:
   1279                     break
   1280 
   1281             self._LineIndex = LineStart - 1
   1282             self._ValueList = [V1, V2, V3]
   1283 
   1284             if Owner > 0 and Owner in self._IdMapping:
   1285                 self._InSubsection = True
   1286             else:
   1287                 self._InSubsection = False
   1288             try:
   1289                 Processer[self._ItemType]()
   1290             except EvaluationException, Excpt:
   1291                 # 

   1292                 # Only catch expression evaluation error here. We need to report

   1293                 # the precise number of line on which the error occurred

   1294                 #

   1295                 if hasattr(Excpt, 'Pcd'):
   1296                     if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
   1297                         Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
   1298                         EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
   1299                                         " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
   1300                                         " of the DSC file, and it is currently defined in this section:"
   1301                                         " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
   1302                                     File=self._FileWithError, ExtraData=' '.join(self._ValueList),
   1303                                     Line=self._LineIndex + 1)
   1304                     else:
   1305                         EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
   1306                                     File=self._FileWithError, ExtraData=' '.join(self._ValueList),
   1307                                     Line=self._LineIndex + 1)
   1308                 else:
   1309                     EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
   1310                                     File=self._FileWithError, ExtraData=' '.join(self._ValueList),
   1311                                     Line=self._LineIndex + 1)
   1312             except MacroException, Excpt:
   1313                 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
   1314                                 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
   1315                                 Line=self._LineIndex + 1)
   1316 
   1317             if self._ValueList == None:
   1318                 continue
   1319 
   1320             NewOwner = self._IdMapping.get(Owner, -1)
   1321             self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
   1322             self._LastItem = self._Store(
   1323                                 self._ItemType,
   1324                                 self._ValueList[0],
   1325                                 self._ValueList[1],
   1326                                 self._ValueList[2],
   1327                                 S1,
   1328                                 S2,
   1329                                 NewOwner,
   1330                                 self._From,
   1331                                 self._LineIndex + 1,
   1332                                 - 1,
   1333                                 self._LineIndex + 1,
   1334                                 - 1,
   1335                                 self._Enabled
   1336                                 )
   1337             self._IdMapping[Id] = self._LastItem
   1338 
   1339         GlobalData.gPlatformDefines.update(self._FileLocalMacros)
   1340         self._PostProcessed = True
   1341         self._Content = None
   1342 
   1343     def __ProcessSectionHeader(self):
   1344         self._SectionName = self._ValueList[0]
   1345         if self._SectionName in self.DataType:
   1346             self._SectionType = self.DataType[self._SectionName]
   1347         else:
   1348             self._SectionType = MODEL_UNKNOWN
   1349 
   1350     def __ProcessSubsectionHeader(self):
   1351         self._SubsectionName = self._ValueList[0]
   1352         if self._SubsectionName in self.DataType:
   1353             self._SubsectionType = self.DataType[self._SubsectionName]
   1354         else:
   1355             self._SubsectionType = MODEL_UNKNOWN
   1356 
   1357     def __RetrievePcdValue(self):
   1358         Content = open(str(self.MetaFile), 'r').readlines()
   1359         GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
   1360         for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
   1361                         MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
   1362                         MODEL_PCD_DYNAMIC_EX_VPD):
   1363             Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
   1364             for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
   1365                 Name = TokenSpaceGuid + '.' + PcdName
   1366                 if Name not in GlobalData.gPlatformOtherPcds:
   1367                     PcdLine = Line
   1368                     while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
   1369                         Line -= 1
   1370                     GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
   1371 
   1372     def __ProcessDefine(self):
   1373         if not self._Enabled:
   1374             return
   1375 
   1376         Type, Name, Value = self._ValueList
   1377         Value = ReplaceMacro(Value, self._Macros, False)
   1378         #

   1379         # If it is <Defines>, return

   1380         #

   1381         if self._InSubsection:
   1382             self._ValueList = [Type, Name, Value]
   1383             return
   1384 
   1385         if self._ItemType == MODEL_META_DATA_DEFINE:
   1386             if self._SectionType == MODEL_META_DATA_HEADER:
   1387                 self._FileLocalMacros[Name] = Value
   1388             else:
   1389                 self._ConstructSectionMacroDict(Name, Value)
   1390         elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
   1391             GlobalData.gEdkGlobal[Name] = Value
   1392 
   1393         #

   1394         # Keyword in [Defines] section can be used as Macros

   1395         #

   1396         if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
   1397             self._FileLocalMacros[Name] = Value
   1398 
   1399         self._ValueList = [Type, Name, Value]
   1400 
   1401     def __ProcessDirective(self):
   1402         Result = None
   1403         if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
   1404                               MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
   1405             Macros = self._Macros
   1406             Macros.update(GlobalData.gGlobalDefines)
   1407             try:
   1408                 Result = ValueExpression(self._ValueList[1], Macros)()
   1409             except SymbolNotFound, Exc:
   1410                 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
   1411                 Result = False
   1412             except WrnExpression, Excpt:
   1413                 # 

   1414                 # Catch expression evaluation warning here. We need to report

   1415                 # the precise number of line and return the evaluation result

   1416                 #

   1417                 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
   1418                                 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
   1419                                 Line=self._LineIndex + 1)
   1420                 Result = Excpt.result
   1421 
   1422         if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
   1423                               MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
   1424                               MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
   1425             self._DirectiveStack.append(self._ItemType)
   1426             if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
   1427                 Result = bool(Result)
   1428             else:
   1429                 Macro = self._ValueList[1]
   1430                 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
   1431                 Result = Macro in self._Macros
   1432                 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
   1433                     Result = not Result
   1434             self._DirectiveEvalStack.append(Result)
   1435         elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
   1436             self._DirectiveStack.append(self._ItemType)
   1437             self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
   1438             self._DirectiveEvalStack.append(bool(Result))
   1439         elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
   1440             self._DirectiveStack.append(self._ItemType)
   1441             self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
   1442             self._DirectiveEvalStack.append(True)
   1443         elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
   1444             # Back to the nearest !if/!ifdef/!ifndef

   1445             while self._DirectiveStack:
   1446                 self._DirectiveEvalStack.pop()
   1447                 Directive = self._DirectiveStack.pop()
   1448                 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
   1449                                  MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
   1450                                  MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
   1451                     break
   1452         elif self._ItemType == MODEL_META_DATA_INCLUDE:
   1453             # The included file must be relative to workspace or same directory as DSC file

   1454             __IncludeMacros = {}
   1455             #

   1456             # Allow using system environment variables  in path after !include

   1457             #

   1458             __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
   1459             if "ECP_SOURCE" in GlobalData.gGlobalDefines.keys():
   1460                 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']
   1461             #

   1462             # During GenFds phase call DSC parser, will go into this branch.

   1463             #

   1464             elif "ECP_SOURCE" in GlobalData.gCommandLineDefines.keys():
   1465                 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']
   1466 
   1467             __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']
   1468             __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']
   1469             #

   1470             # Allow using MACROs comes from [Defines] section to keep compatible. 

   1471             #

   1472             __IncludeMacros.update(self._Macros)
   1473 
   1474             IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
   1475             #

   1476             # First search the include file under the same directory as DSC file

   1477             #

   1478             IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
   1479             ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
   1480             if ErrorCode != 0:
   1481                 #

   1482                 # Also search file under the WORKSPACE directory

   1483                 #

   1484                 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
   1485                 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
   1486                 if ErrorCode != 0:
   1487                     EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
   1488                                     Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
   1489 
   1490             self._FileWithError = IncludedFile1
   1491 
   1492             IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False)
   1493             Owner = self._Content[self._ContentIndex - 1][0]
   1494             Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,
   1495                                Owner=Owner, From=Owner)
   1496 
   1497             # Does not allow lower level included file to include upper level included file

   1498             if Parser._From != Owner and int(Owner) > int (Parser._From):
   1499                 EdkLogger.error('parser', FILE_ALREADY_EXIST, File=self._FileWithError,
   1500                     Line=self._LineIndex + 1, ExtraData="{0} is already included at a higher level.".format(IncludedFile1))
   1501 
   1502 
   1503             # set the parser status with current status

   1504             Parser._SectionName = self._SectionName
   1505             Parser._SectionType = self._SectionType
   1506             Parser._Scope = self._Scope
   1507             Parser._Enabled = self._Enabled
   1508             # Parse the included file

   1509             Parser.Start()
   1510 
   1511             # update current status with sub-parser's status

   1512             self._SectionName = Parser._SectionName
   1513             self._SectionType = Parser._SectionType
   1514             self._Scope = Parser._Scope
   1515             self._Enabled = Parser._Enabled
   1516 
   1517             # Insert all records in the table for the included file into dsc file table

   1518             Records = IncludedFileTable.GetAll()
   1519             if Records:
   1520                 self._Content[self._ContentIndex:self._ContentIndex] = Records
   1521                 self._Content.pop(self._ContentIndex - 1)
   1522                 self._ValueList = None
   1523                 self._ContentIndex -= 1
   1524 
   1525     def __ProcessSkuId(self):
   1526         self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
   1527                            for Value in self._ValueList]
   1528 
   1529     def __ProcessLibraryInstance(self):
   1530         self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
   1531 
   1532     def __ProcessLibraryClass(self):
   1533         self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
   1534 
   1535     def __ProcessPcd(self):
   1536         if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
   1537             self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
   1538             return
   1539 
   1540         ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
   1541         if not Valid:
   1542             EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,
   1543                             ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
   1544         PcdValue = ValList[Index]
   1545         if PcdValue:
   1546             try:
   1547                 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
   1548             except WrnExpression, Value:
   1549                 ValList[Index] = Value.result
   1550 
   1551         if ValList[Index] == 'True':
   1552             ValList[Index] = '1'
   1553         if ValList[Index] == 'False':
   1554             ValList[Index] = '0'
   1555 
   1556         if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):
   1557             GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
   1558             self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
   1559         self._ValueList[2] = '|'.join(ValList)
   1560 
   1561     def __ProcessComponent(self):
   1562         self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
   1563 
   1564     def __ProcessSourceOverridePath(self):
   1565         self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
   1566 
   1567     def __ProcessBuildOption(self):
   1568         self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
   1569                            for Value in self._ValueList]
   1570 
   1571     _SectionParser = {
   1572         MODEL_META_DATA_HEADER                          :   _DefineParser,
   1573         MODEL_EFI_SKU_ID                                :   _SkuIdParser,
   1574         MODEL_EFI_LIBRARY_INSTANCE                      :   _LibraryInstanceParser,
   1575         MODEL_EFI_LIBRARY_CLASS                         :   _LibraryClassParser,
   1576         MODEL_PCD_FIXED_AT_BUILD                        :   _PcdParser,
   1577         MODEL_PCD_PATCHABLE_IN_MODULE                   :   _PcdParser,
   1578         MODEL_PCD_FEATURE_FLAG                          :   _PcdParser,
   1579         MODEL_PCD_DYNAMIC_DEFAULT                       :   _PcdParser,
   1580         MODEL_PCD_DYNAMIC_HII                           :   _PcdParser,
   1581         MODEL_PCD_DYNAMIC_VPD                           :   _PcdParser,
   1582         MODEL_PCD_DYNAMIC_EX_DEFAULT                    :   _PcdParser,
   1583         MODEL_PCD_DYNAMIC_EX_HII                        :   _PcdParser,
   1584         MODEL_PCD_DYNAMIC_EX_VPD                        :   _PcdParser,
   1585         MODEL_META_DATA_COMPONENT                       :   _ComponentParser,
   1586         MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH  :   _CompponentSourceOverridePathParser,
   1587         MODEL_META_DATA_BUILD_OPTION                    :   _BuildOptionParser,
   1588         MODEL_UNKNOWN                                   :   MetaFileParser._Skip,
   1589         MODEL_META_DATA_USER_EXTENSION                  :   MetaFileParser._SkipUserExtension,
   1590         MODEL_META_DATA_SECTION_HEADER                  :   MetaFileParser._SectionHeaderParser,
   1591         MODEL_META_DATA_SUBSECTION_HEADER               :   _SubsectionHeaderParser,
   1592     }
   1593 
   1594     _Macros = property(_GetMacros)
   1595 
   1596 ## DEC file parser class

   1597 #

   1598 #   @param      FilePath        The path of platform description file

   1599 #   @param      FileType        The raw data of DSC file

   1600 #   @param      Table           Database used to retrieve module/package information

   1601 #   @param      Macros          Macros used for replacement in file

   1602 #

   1603 class DecParser(MetaFileParser):
   1604     # DEC file supported data types (one type per section)

   1605     DataType = {
   1606         TAB_DEC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,
   1607         TAB_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,
   1608         TAB_INCLUDES.upper()                        :   MODEL_EFI_INCLUDE,
   1609         TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,
   1610         TAB_GUIDS.upper()                           :   MODEL_EFI_GUID,
   1611         TAB_PPIS.upper()                            :   MODEL_EFI_PPI,
   1612         TAB_PROTOCOLS.upper()                       :   MODEL_EFI_PROTOCOL,
   1613         TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,
   1614         TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,
   1615         TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,
   1616         TAB_PCDS_DYNAMIC_NULL.upper()               :   MODEL_PCD_DYNAMIC,
   1617         TAB_PCDS_DYNAMIC_EX_NULL.upper()            :   MODEL_PCD_DYNAMIC_EX,
   1618         TAB_USER_EXTENSIONS.upper()                 :   MODEL_META_DATA_USER_EXTENSION,
   1619     }
   1620 
   1621     ## Constructor of DecParser

   1622     #

   1623     #  Initialize object of DecParser

   1624     #

   1625     #   @param      FilePath        The path of platform description file

   1626     #   @param      FileType        The raw data of DSC file

   1627     #   @param      Arch            Default Arch value for filtering sections

   1628     #   @param      Table           Database used to retrieve module/package information

   1629     #

   1630     def __init__(self, FilePath, FileType, Arch, Table):
   1631         # prevent re-initialization

   1632         if hasattr(self, "_Table"):
   1633             return
   1634         MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)
   1635         self._Comments = []
   1636         self._Version = 0x00010005  # Only EDK2 dec file is supported

   1637         self._AllPCDs = [] # Only for check duplicate PCD

   1638         self._AllPcdDict = {}
   1639 
   1640     ## Parser starter

   1641     def Start(self):
   1642         Content = ''
   1643         try:
   1644             Content = open(str(self.MetaFile), 'r').readlines()
   1645         except:
   1646             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
   1647 
   1648         for Index in range(0, len(Content)):
   1649             Line, Comment = CleanString2(Content[Index])
   1650             self._CurrentLine = Line
   1651             self._LineIndex = Index
   1652 
   1653             # save comment for later use

   1654             if Comment:
   1655                 self._Comments.append((Comment, self._LineIndex + 1))
   1656             # skip empty line

   1657             if Line == '':
   1658                 continue
   1659 
   1660             # section header

   1661             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
   1662                 self._SectionHeaderParser()
   1663                 self._Comments = []
   1664                 continue
   1665             elif len(self._SectionType) == 0:
   1666                 self._Comments = []
   1667                 continue
   1668 
   1669             # section content

   1670             self._ValueList = ['', '', '']
   1671             self._SectionParser[self._SectionType[0]](self)
   1672             if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
   1673                 self._ItemType = -1
   1674                 self._Comments = []
   1675                 continue
   1676 
   1677             #

   1678             # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,

   1679             # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1

   1680             #

   1681             for Arch, ModuleType, Type in self._Scope:
   1682                 self._LastItem = self._Store(
   1683                     Type,
   1684                     self._ValueList[0],
   1685                     self._ValueList[1],
   1686                     self._ValueList[2],
   1687                     Arch,
   1688                     ModuleType,
   1689                     self._Owner[-1],
   1690                     self._LineIndex + 1,
   1691                     - 1,
   1692                     self._LineIndex + 1,
   1693                     - 1,
   1694                     0
   1695                     )
   1696                 for Comment, LineNo in self._Comments:
   1697                     self._Store(
   1698                         MODEL_META_DATA_COMMENT,
   1699                         Comment,
   1700                         self._ValueList[0],
   1701                         self._ValueList[1],
   1702                         Arch,
   1703                         ModuleType,
   1704                         self._LastItem,
   1705                         LineNo,
   1706                         - 1,
   1707                         LineNo,
   1708                         - 1,
   1709                         0
   1710                         )
   1711             self._Comments = []
   1712         self._Done()
   1713 
   1714 
   1715     ## Section header parser

   1716     #

   1717     #   The section header is always in following format:

   1718     #

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

   1720     #

   1721     def _SectionHeaderParser(self):
   1722         self._Scope = []
   1723         self._SectionName = ''
   1724         self._SectionType = []
   1725         ArchList = set()
   1726         PrivateList = set()
   1727         Line = self._CurrentLine.replace("%s%s" % (TAB_COMMA_SPLIT, TAB_SPACE_SPLIT), TAB_COMMA_SPLIT)
   1728         for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
   1729             if Item == '':
   1730                 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
   1731                                 "section name can NOT be empty or incorrectly use separator comma",
   1732                                 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
   1733             ItemList = Item.split(TAB_SPLIT)
   1734 
   1735             # different types of PCD are permissible in one section

   1736             self._SectionName = ItemList[0].upper()
   1737             if self._SectionName in self.DataType:
   1738                 if self.DataType[self._SectionName] not in self._SectionType:
   1739                     self._SectionType.append(self.DataType[self._SectionName])
   1740             else:
   1741                 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
   1742                                 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
   1743 
   1744             if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
   1745                 EdkLogger.error(
   1746                             'Parser',
   1747                             FORMAT_INVALID,
   1748                             "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
   1749                             File=self.MetaFile,
   1750                             Line=self._LineIndex + 1,
   1751                             ExtraData=self._CurrentLine
   1752                             )
   1753             # S1 is always Arch

   1754             if len(ItemList) > 1:
   1755                 S1 = ItemList[1].upper()
   1756             else:
   1757                 S1 = 'COMMON'
   1758             ArchList.add(S1)
   1759             # S2 may be Platform or ModuleType

   1760             if len(ItemList) > 2:
   1761                 S2 = ItemList[2].upper()
   1762                 # only Includes, GUIDs, PPIs, Protocols section have Private tag

   1763                 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:
   1764                     if S2 != 'PRIVATE':
   1765                         EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',
   1766                                         File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
   1767             else:
   1768                 S2 = 'COMMON'
   1769             PrivateList.add(S2)
   1770             if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
   1771                 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
   1772 
   1773         # 'COMMON' must not be used with specific ARCHs at the same section

   1774         if 'COMMON' in ArchList and len(ArchList) > 1:
   1775             EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
   1776                             File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
   1777 
   1778         # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute

   1779         if 'COMMON' in PrivateList and len(PrivateList) > 1:
   1780             EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
   1781                             File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
   1782 
   1783     ## [guids], [ppis] and [protocols] section parser

   1784     @ParseMacro
   1785     def _GuidParser(self):
   1786         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
   1787         if len(TokenList) < 2:
   1788             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
   1789                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
   1790                             File=self.MetaFile, Line=self._LineIndex + 1)
   1791         if TokenList[0] == '':
   1792             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
   1793                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
   1794                             File=self.MetaFile, Line=self._LineIndex + 1)
   1795         if TokenList[1] == '':
   1796             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
   1797                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
   1798                             File=self.MetaFile, Line=self._LineIndex + 1)
   1799         if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
   1800             EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
   1801                             ExtraData=self._CurrentLine + \
   1802                                       " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
   1803                             File=self.MetaFile, Line=self._LineIndex + 1)
   1804         self._ValueList[0] = TokenList[0]
   1805         self._ValueList[1] = TokenList[1]
   1806 
   1807     ## PCD sections parser

   1808     #

   1809     #   [PcdsFixedAtBuild]

   1810     #   [PcdsPatchableInModule]

   1811     #   [PcdsFeatureFlag]

   1812     #   [PcdsDynamicEx

   1813     #   [PcdsDynamic]

   1814     #

   1815     @ParseMacro
   1816     def _PcdParser(self):
   1817         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
   1818         self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
   1819         ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
   1820         # check PCD information

   1821         if self._ValueList[0] == '' or self._ValueList[1] == '':
   1822             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
   1823                             ExtraData=self._CurrentLine + \
   1824                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1825                             File=self.MetaFile, Line=self._LineIndex + 1)
   1826         # check format of token space GUID CName

   1827         if not ValueRe.match(self._ValueList[0]):
   1828             EdkLogger.error('Parser', FORMAT_INVALID, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
   1829                             ExtraData=self._CurrentLine + \
   1830                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1831                             File=self.MetaFile, Line=self._LineIndex + 1)
   1832         # check format of PCD CName

   1833         if not ValueRe.match(self._ValueList[1]):
   1834             EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
   1835                             ExtraData=self._CurrentLine + \
   1836                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1837                             File=self.MetaFile, Line=self._LineIndex + 1)
   1838         # check PCD datum information

   1839         if len(TokenList) < 2 or TokenList[1] == '':
   1840             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
   1841                             ExtraData=self._CurrentLine + \
   1842                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1843                             File=self.MetaFile, Line=self._LineIndex + 1)
   1844 
   1845 
   1846         ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
   1847         PtrValue = ValueRe.findall(TokenList[1])
   1848 
   1849         # Has VOID* type string, may contain "|" character in the string. 

   1850         if len(PtrValue) != 0:
   1851             ptrValueList = re.sub(ValueRe, '', TokenList[1])
   1852             ValueList = AnalyzePcdExpression(ptrValueList)
   1853             ValueList[0] = PtrValue[0]
   1854         else:
   1855             ValueList = AnalyzePcdExpression(TokenList[1])
   1856 
   1857 
   1858         # check if there's enough datum information given

   1859         if len(ValueList) != 3:
   1860             EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
   1861                             ExtraData=self._CurrentLine + \
   1862                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1863                             File=self.MetaFile, Line=self._LineIndex + 1)
   1864         # check default value

   1865         if ValueList[0] == '':
   1866             EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
   1867                             ExtraData=self._CurrentLine + \
   1868                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1869                             File=self.MetaFile, Line=self._LineIndex + 1)
   1870         # check datum type

   1871         if ValueList[1] == '':
   1872             EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
   1873                             ExtraData=self._CurrentLine + \
   1874                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1875                             File=self.MetaFile, Line=self._LineIndex + 1)
   1876         # check token of the PCD

   1877         if ValueList[2] == '':
   1878             EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
   1879                             ExtraData=self._CurrentLine + \
   1880                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1881                             File=self.MetaFile, Line=self._LineIndex + 1)
   1882 
   1883         PcdValue = ValueList[0]
   1884         if PcdValue:
   1885             try:
   1886                 ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)
   1887             except WrnExpression, Value:
   1888                 ValueList[0] = Value.result
   1889 
   1890         if ValueList[0] == 'True':
   1891             ValueList[0] = '1'
   1892         if ValueList[0] == 'False':
   1893             ValueList[0] = '0'
   1894 
   1895         # check format of default value against the datum type

   1896         IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
   1897         if not IsValid:
   1898             EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
   1899                             File=self.MetaFile, Line=self._LineIndex + 1)
   1900 
   1901         if ValueList[0] in ['True', 'true', 'TRUE']:
   1902             ValueList[0] = '1'
   1903         elif ValueList[0] in ['False', 'false', 'FALSE']:
   1904             ValueList[0] = '0'
   1905 
   1906         # check for duplicate PCD definition

   1907         if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
   1908             EdkLogger.error('Parser', FORMAT_INVALID,
   1909                             "The same PCD name and GUID have been already defined",
   1910                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
   1911         else:
   1912             self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
   1913             self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]
   1914 
   1915         self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
   1916 
   1917     _SectionParser = {
   1918         MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,
   1919         MODEL_EFI_INCLUDE               :   MetaFileParser._PathParser,
   1920         MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,
   1921         MODEL_EFI_GUID                  :   _GuidParser,
   1922         MODEL_EFI_PPI                   :   _GuidParser,
   1923         MODEL_EFI_PROTOCOL              :   _GuidParser,
   1924         MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,
   1925         MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,
   1926         MODEL_PCD_FEATURE_FLAG          :   _PcdParser,
   1927         MODEL_PCD_DYNAMIC               :   _PcdParser,
   1928         MODEL_PCD_DYNAMIC_EX            :   _PcdParser,
   1929         MODEL_UNKNOWN                   :   MetaFileParser._Skip,
   1930         MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._SkipUserExtension,
   1931     }
   1932 
   1933 ##

   1934 #

   1935 # This acts like the main() function for the script, unless it is 'import'ed into another

   1936 # script.

   1937 #

   1938 if __name__ == '__main__':
   1939     pass
   1940 
   1941