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

      2 # This file is used to parse meta files

      3 #

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

      5 # This program and the accompanying materials

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

      7 # which accompanies this distribution.  The full text of the license may be found at

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

      9 #

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

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

     12 #

     13 
     14 ##

     15 # Import Modules

     16 #

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

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

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

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

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

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

     70         if Type == TAB_DSC_DEFINES_DEFINE:
     71             if type(self) == DecParser:
     72                 if MODEL_META_DATA_HEADER in self._SectionType:
     73                     self._FileLocalMacros[Name] = Value
     74                 else:
     75                     for Scope in self._Scope:
     76                         self._SectionsMacroDict.setdefault((Scope[2], Scope[0], Scope[1]), {})[Name] = Value
     77             elif self._SectionType == MODEL_META_DATA_HEADER:
     78                 self._FileLocalMacros[Name] = Value
     79             else:
     80                 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
     81                 if SectionDictKey not in self._SectionsMacroDict:
     82                     self._SectionsMacroDict[SectionDictKey] = {}
     83                 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
     84                 SectionLocalMacros[Name] = Value
     85         # EDK_GLOBAL defined macros

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

    101 #

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

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

    104 #

    105 #   @param      FilePath        The path of platform description file

    106 #   @param      FileType        The raw data of DSC file

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

    108 #   @param      Macros          Macros used for replacement in file

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

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

    111 #

    112 class MetaFileParser(object):
    113     # data type (file content) for specific file type

    114     DataType = {}
    115 
    116     # Parser objects used to implement singleton

    117     MetaFiles = {}
    118 
    119     ## Factory method

    120     #

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

    122     # only one object constructed for one meta file.

    123     #

    124     #   @param  Class           class object of real AutoGen class

    125     #                           (InfParser, DecParser or DscParser)

    126     #   @param  FilePath        The path of meta file

    127     #   @param  *args           The specific class related parameters

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

    129     #

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

    139     #

    140     #  Initialize object of MetaFileParser

    141     #

    142     #   @param      FilePath        The path of platform description file

    143     #   @param      FileType        The raw data of DSC file

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

    145     #   @param      Macros          Macros used for replacement in file

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

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

    148     #

    149     def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):
    150         self._Table = Table
    151         self._RawTable = Table
    152         self._FileType = FileType
    153         self.MetaFile = FilePath
    154         self._Defines = {}
    155         self._FileLocalMacros = {}
    156         self._SectionsMacroDict = {}
    157 
    158         # for recursive parsing

    159         self._Owner = [Owner]
    160         self._From = From
    161 
    162         # parsr status for parsing

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

    178         self._Version = 0
    179         # UNI object and extra UNI object

    180         self._UniObj = None
    181         self._UniExtraObj = None
    182 
    183     ## Store the parsed data in table

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

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

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

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

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

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

    210     def _SetFinished(self, Value):
    211         self._Finished = Value
    212 
    213     ## Use [] style to query data in table, just for readability

    214     #

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

    216     #

    217     def __getitem__(self, DataInfo):
    218         if type(DataInfo) != type(()):
    219             DataInfo = (DataInfo,)
    220 
    221         # Parse the file first, if necessary

    222         if not self._Finished:
    223             if self._RawTable.IsIntegrity():
    224                 self._Finished = True
    225             else:
    226                 self._Table = self._RawTable
    227                 self._PostProcessed = False
    228                 self.Start()
    229 
    230         # No specific ARCH or Platform given, use raw data

    231         if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] == None):
    232             return self._RawTable.Query(*DataInfo)
    233 
    234         # Do post-process if necessary

    235         if not self._PostProcessed:
    236             self._PostProcess()
    237 
    238         return self._Table.Query(*DataInfo)
    239 
    240     ## Data parser for the common format in different type of file

    241     #

    242     #   The common format in the meatfile is like

    243     #

    244     #       xxx1 | xxx2 | xxx3

    245     #

    246     @ParseMacro
    247     def _CommonParser(self):
    248         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
    249         self._ValueList[0:len(TokenList)] = TokenList
    250 
    251     ## Data parser for the format in which there's path

    252     #

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

    254     #

    255     @ParseMacro
    256     def _PathParser(self):
    257         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
    258         self._ValueList[0:len(TokenList)] = TokenList
    259         # Don't do macro replacement for dsc file at this point

    260         if type(self) != DscParser:
    261             Macros = self._Macros
    262             self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
    263 
    264     ## Skip unsupported data

    265     def _Skip(self):
    266         if self._SectionName == TAB_USER_EXTENSIONS.upper() and self._CurrentLine.upper().endswith('.UNI'):
    267             if EccGlobalData.gConfig.UniCheckHelpInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
    268                 ExtraUni = self._CurrentLine.strip()
    269                 ExtraUniFile = os.path.join(os.path.dirname(self.MetaFile), ExtraUni)
    270                 IsModuleUni = self.MetaFile.upper().endswith('.INF')
    271                 self._UniExtraObj = UniParser(ExtraUniFile, IsExtraUni=True, IsModuleUni=IsModuleUni)
    272                 self._UniExtraObj.Start()
    273         else:
    274             EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
    275                             Line=self._LineIndex + 1, ExtraData=self._CurrentLine);
    276         self._ValueList[0:1] = [self._CurrentLine]
    277 
    278     ## Section header parser

    279     #

    280     #   The section header is always in following format:

    281     #

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

    283     #

    284     def _SectionHeaderParser(self):
    285         self._Scope = []
    286         self._SectionName = ''
    287         ArchList = set()
    288         for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
    289             if Item == '':
    290                 continue
    291             ItemList = GetSplitValueList(Item, TAB_SPLIT)
    292             # different section should not mix in one section

    293             if self._SectionName != '' and self._SectionName != ItemList[0].upper():
    294                 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
    295                                 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
    296             self._SectionName = ItemList[0].upper()
    297             if self._SectionName in self.DataType:
    298                 self._SectionType = self.DataType[self._SectionName]
    299             else:
    300                 self._SectionType = MODEL_UNKNOWN
    301                 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
    302                                 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
    303             # S1 is always Arch

    304             if len(ItemList) > 1:
    305                 S1 = ItemList[1].upper()
    306             else:
    307                 S1 = 'COMMON'
    308             ArchList.add(S1)
    309             # S2 may be Platform or ModuleType

    310             if len(ItemList) > 2:
    311                 S2 = ItemList[2].upper()
    312             else:
    313                 S2 = 'COMMON'
    314             self._Scope.append([S1, S2])
    315 
    316         # 'COMMON' must not be used with specific ARCHs at the same section

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

    321         self._ValueList[0] = self._SectionName
    322 
    323     ## [defines] section parser

    324     @ParseMacro
    325     def _DefineParser(self):
    326         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
    327         self._ValueList[1:len(TokenList)] = TokenList
    328         if not self._ValueList[1]:
    329             EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
    330                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
    331         if not self._ValueList[2]:
    332             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
    333                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
    334 
    335         self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
    336         Name, Value = self._ValueList[1], self._ValueList[2]
    337         # Sometimes, we need to make differences between EDK and EDK2 modules 

    338         if Name == 'INF_VERSION':
    339             try:
    340                 self._Version = int(Value, 0)
    341             except:
    342                 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
    343                                 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
    344         elif Name == 'MODULE_UNI_FILE':
    345             UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)
    346             if os.path.exists(UniFile):
    347                 self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=True)
    348                 self._UniObj.Start()
    349             else:
    350                 EdkLogger.error('Parser', FILE_NOT_FOUND, "Module UNI file %s is missing." % Value,
    351                                 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1,
    352                                 RaiseError=False)
    353         elif Name == 'PACKAGE_UNI_FILE':
    354             UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)
    355             if os.path.exists(UniFile):
    356                 self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=False)
    357         
    358         if type(self) == InfParser and self._Version < 0x00010005:
    359             # EDK module allows using defines as macros

    360             self._FileLocalMacros[Name] = Value
    361         self._Defines[Name] = Value
    362 
    363     ## [BuildOptions] section parser

    364     @ParseMacro
    365     def _BuildOptionParser(self):
    366         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
    367         TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
    368         if len(TokenList2) == 2:
    369             self._ValueList[0] = TokenList2[0]              # toolchain family

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

    371         else:
    372             self._ValueList[1] = TokenList[0]
    373         if len(TokenList) == 2 and type(self) != DscParser: # value

    374             self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
    375 
    376         if self._ValueList[1].count('_') != 4:
    377             EdkLogger.error(
    378                 'Parser',
    379                 FORMAT_INVALID,
    380                 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
    381                 ExtraData=self._CurrentLine,
    382                 File=self.MetaFile,
    383                 Line=self._LineIndex+1
    384                 )
    385 
    386     def _GetMacros(self):
    387         Macros = {}
    388         Macros.update(self._FileLocalMacros)
    389         Macros.update(self._GetApplicableSectionMacro())
    390         return Macros
    391 
    392 
    393     ## Get section Macros that are applicable to current line, which may come from other sections 

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

    395     def _GetApplicableSectionMacro(self):
    396         Macros = {}
    397         for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", self._Scope[0][1]),
    398                                (self._Scope[0][0], "COMMON"), (self._Scope[0][0], self._Scope[0][1])]:
    399             if (self._SectionType, Scope1, Scope2) in self._SectionsMacroDict:
    400                 Macros.update(self._SectionsMacroDict[(self._SectionType, Scope1, Scope2)])
    401         return Macros
    402 
    403     _SectionParser  = {}
    404     Finished        = property(_GetFinished, _SetFinished)
    405     _Macros         = property(_GetMacros)
    406 
    407 
    408 ## INF file parser class

    409 #

    410 #   @param      FilePath        The path of platform description file

    411 #   @param      FileType        The raw data of DSC file

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

    413 #   @param      Macros          Macros used for replacement in file

    414 #

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

    417     DataType = {
    418         TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
    419         TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
    420         TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
    421         TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
    422         TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
    423         TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
    424         TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
    425         TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
    426         TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
    427         TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
    428         TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
    429         TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
    430         TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
    431         TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
    432         TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
    433         TAB_GUIDS.upper() : MODEL_EFI_GUID,
    434         TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
    435         TAB_PPIS.upper() : MODEL_EFI_PPI,
    436         TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
    437         TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
    438         TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
    439     }
    440 
    441     ## Constructor of InfParser

    442     #

    443     #  Initialize object of InfParser

    444     #

    445     #   @param      FilePath        The path of module description file

    446     #   @param      FileType        The raw data of DSC file

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

    448     #   @param      Macros          Macros used for replacement in file

    449     #

    450     def __init__(self, FilePath, FileType, Table):
    451         # prevent re-initialization

    452         if hasattr(self, "_Table"):
    453             return
    454         MetaFileParser.__init__(self, FilePath, FileType, Table)
    455         self.TblFile = EccGlobalData.gDb.TblFile
    456         self.FileID = -1
    457 
    458     ## Parser starter

    459     def Start(self):
    460         NmakeLine = ''
    461         Content = ''
    462         Usage = ''
    463         try:
    464             Content = open(str(self.MetaFile), 'r').readlines()
    465         except:
    466             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
    467         #

    468         # Insert a record for file

    469         #

    470         Filename = NormPath(self.MetaFile)
    471         FileID = self.TblFile.GetFileId(Filename)
    472         if FileID:
    473             self.FileID = FileID
    474         else:
    475             self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_INF)
    476             
    477         # parse the file line by line

    478         IsFindBlockComment = False
    479 
    480         for Index in range(0, len(Content)):
    481             if self._SectionType in [MODEL_EFI_GUID,
    482                                      MODEL_EFI_PROTOCOL,
    483                                      MODEL_EFI_PPI,
    484                                      MODEL_PCD_FIXED_AT_BUILD,
    485                                      MODEL_PCD_PATCHABLE_IN_MODULE,
    486                                      MODEL_PCD_FEATURE_FLAG,
    487                                      MODEL_PCD_DYNAMIC_EX,
    488                                      MODEL_PCD_DYNAMIC]:
    489                 Line = Content[Index].strip()
    490                 if Line.startswith(TAB_SPECIAL_COMMENT):
    491                     Usage += ' ' + Line[Line.find(TAB_SPECIAL_COMMENT):]
    492                     continue
    493                 elif Line.startswith(TAB_COMMENT_SPLIT):
    494                     continue
    495                 elif Line.find(TAB_COMMENT_SPLIT) > 0:
    496                     Usage += ' ' + Line[Line.find(TAB_COMMENT_SPLIT):]
    497                     Line = Line[:Line.find(TAB_COMMENT_SPLIT)]
    498             else:
    499             # skip empty, commented, block commented lines

    500                 Line = CleanString(Content[Index], AllowCppStyleComment=True)
    501                 Usage = ''
    502             NextLine = ''
    503             if Index + 1 < len(Content):
    504                 NextLine = CleanString(Content[Index + 1])
    505             if Line == '':
    506                 continue
    507             if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:
    508                 IsFindBlockComment = True
    509                 continue
    510             if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:
    511                 IsFindBlockComment = False
    512                 continue
    513             if IsFindBlockComment:
    514                 continue
    515 
    516             self._LineIndex = Index
    517             self._CurrentLine = Line
    518 
    519             # section header

    520             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
    521                 self._SectionHeaderParser()
    522                 # Check invalid sections

    523                 if self._Version < 0x00010005:
    524                     if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
    525                                              MODEL_EFI_LIBRARY_CLASS,
    526                                              MODEL_META_DATA_PACKAGE,
    527                                              MODEL_PCD_FIXED_AT_BUILD,
    528                                              MODEL_PCD_PATCHABLE_IN_MODULE,
    529                                              MODEL_PCD_FEATURE_FLAG,
    530                                              MODEL_PCD_DYNAMIC_EX,
    531                                              MODEL_PCD_DYNAMIC,
    532                                              MODEL_EFI_GUID,
    533                                              MODEL_EFI_PROTOCOL,
    534                                              MODEL_EFI_PPI,
    535                                              MODEL_META_DATA_USER_EXTENSION]:
    536                         EdkLogger.error('Parser', FORMAT_INVALID,
    537                                         "Section [%s] is not allowed in inf file without version" % (self._SectionName),
    538                                         ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
    539                 elif self._SectionType in [MODEL_EFI_INCLUDE,
    540                                            MODEL_EFI_LIBRARY_INSTANCE,
    541                                            MODEL_META_DATA_NMAKE]:
    542                     EdkLogger.error('Parser', FORMAT_INVALID,
    543                                     "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
    544                                     ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
    545                 continue
    546             # merge two lines specified by '\' in section NMAKE

    547             elif self._SectionType == MODEL_META_DATA_NMAKE:
    548                 if Line[-1] == '\\':
    549                     if NextLine == '':
    550                         self._CurrentLine = NmakeLine + Line[0:-1]
    551                         NmakeLine = ''
    552                     else:
    553                         if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
    554                             self._CurrentLine = NmakeLine + Line[0:-1]
    555                             NmakeLine = ''
    556                         else:
    557                             NmakeLine = NmakeLine + ' ' + Line[0:-1]
    558                             continue
    559                 else:
    560                     self._CurrentLine = NmakeLine + Line
    561                     NmakeLine = ''
    562 
    563             # section content
    564             self._ValueList = ['','','']
    565             # parse current line, result will be put in self._ValueList
    566             self._SectionParser[self._SectionType](self)
    567             if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
    568                 self._ItemType = -1
    569                 continue
    570             #
    571             # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
    572             # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
    573             #
    574             self._ValueList[0] = self._ValueList[0].replace('/', '\\')
    575             Usage = Usage.strip()
    576             for Arch, Platform in self._Scope:
    577                 self._Store(self._SectionType,
    578                             self._ValueList[0],
    579                             self._ValueList[1],
    580                             self._ValueList[2],
    581                             Arch,
    582                             Platform,
    583                             self._Owner[-1],
    584                             self.FileID,
    585                             self._LineIndex+1,
    586                             -1,
    587                             self._LineIndex+1,
    588                             -1,
    589                             0,
    590                             Usage
    591                             )
    592             Usage = ''
    593         if IsFindBlockComment:
    594             EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */", 
    595                             File=self.MetaFile)
    596         self._Done()
    597 
    598     ## Data parser for the format in which there's path
    599     #

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

    601     #

    602     def _IncludeParser(self):
    603         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
    604         self._ValueList[0:len(TokenList)] = TokenList
    605         Macros = self._Macros
    606         if Macros:
    607             for Index in range(0, len(self._ValueList)):
    608                 Value = self._ValueList[Index]
    609                 if not Value:
    610                     continue
    611 
    612                 if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
    613                     Value = '$(EDK_SOURCE)' + Value[17:]
    614                 if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:
    615                     pass
    616                 elif Value.startswith('.'):
    617                     pass
    618                 elif Value.startswith('$('):
    619                     pass
    620                 else:
    621                     Value = '$(EFI_SOURCE)/' + Value
    622 
    623                 self._ValueList[Index] = ReplaceMacro(Value, Macros)
    624 
    625     ## Parse [Sources] section

    626     #

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

    628     #

    629     @ParseMacro
    630     def _SourceFileParser(self):
    631         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
    632         self._ValueList[0:len(TokenList)] = TokenList
    633         Macros = self._Macros
    634         # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'

    635         if 'COMPONENT_TYPE' in Macros:
    636             if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
    637                 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
    638         if self._Defines['BASE_NAME'] == 'Microcode':
    639             pass
    640         self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
    641 
    642     ## Parse [Binaries] section

    643     #

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

    645     #

    646     @ParseMacro
    647     def _BinaryFileParser(self):
    648         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
    649         if len(TokenList) < 2:
    650             EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
    651                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
    652                             File=self.MetaFile, Line=self._LineIndex+1)
    653         if not TokenList[0]:
    654             EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
    655                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
    656                             File=self.MetaFile, Line=self._LineIndex+1)
    657         if not TokenList[1]:
    658             EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
    659                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
    660                             File=self.MetaFile, Line=self._LineIndex+1)
    661         self._ValueList[0:len(TokenList)] = TokenList
    662         self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
    663 
    664     ## [nmake] section parser (Edk.x style only)

    665     def _NmakeParser(self):
    666         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
    667         self._ValueList[0:len(TokenList)] = TokenList
    668         # remove macros

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

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

    672 
    673     ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser

    674     @ParseMacro
    675     def _PcdParser(self):
    676         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
    677         ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
    678         if len(ValueList) != 2:
    679             EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
    680                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
    681                             File=self.MetaFile, Line=self._LineIndex+1)
    682         self._ValueList[0:1] = ValueList
    683         if len(TokenList) > 1:
    684             self._ValueList[2] = TokenList[1]
    685         if self._ValueList[0] == '' or self._ValueList[1] == '':
    686             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
    687                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
    688                             File=self.MetaFile, Line=self._LineIndex+1)
    689 
    690         # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.

    691         if self._ValueList[2] != '':
    692             InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
    693             if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
    694                 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
    695             elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
    696                 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
    697 
    698     ## [depex] section parser

    699     @ParseMacro
    700     def _DepexParser(self):
    701         self._ValueList[0:1] = [self._CurrentLine]
    702 
    703     _SectionParser = {
    704         MODEL_UNKNOWN                   :   MetaFileParser._Skip,
    705         MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,
    706         MODEL_META_DATA_BUILD_OPTION    :   MetaFileParser._BuildOptionParser,
    707         MODEL_EFI_INCLUDE               :   _IncludeParser,                 # for Edk.x modules

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

    709         MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,
    710         MODEL_META_DATA_PACKAGE         :   MetaFileParser._PathParser,
    711         MODEL_META_DATA_NMAKE           :   _NmakeParser,                   # for Edk.x modules

    712         MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,
    713         MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,
    714         MODEL_PCD_FEATURE_FLAG          :   _PcdParser,
    715         MODEL_PCD_DYNAMIC_EX            :   _PcdParser,
    716         MODEL_PCD_DYNAMIC               :   _PcdParser,
    717         MODEL_EFI_SOURCE_FILE           :   _SourceFileParser,
    718         MODEL_EFI_GUID                  :   MetaFileParser._CommonParser,
    719         MODEL_EFI_PROTOCOL              :   MetaFileParser._CommonParser,
    720         MODEL_EFI_PPI                   :   MetaFileParser._CommonParser,
    721         MODEL_EFI_DEPEX                 :   _DepexParser,
    722         MODEL_EFI_BINARY_FILE           :   _BinaryFileParser,
    723         MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._Skip,
    724     }
    725 
    726 ## DSC file parser class

    727 #

    728 #   @param      FilePath        The path of platform description file

    729 #   @param      FileType        The raw data of DSC file

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

    731 #   @param      Macros          Macros used for replacement in file

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

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

    734 #

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

    737     DataType = {
    738         TAB_SKUIDS.upper()                          :   MODEL_EFI_SKU_ID,
    739         TAB_LIBRARIES.upper()                       :   MODEL_EFI_LIBRARY_INSTANCE,
    740         TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,
    741         TAB_BUILD_OPTIONS.upper()                   :   MODEL_META_DATA_BUILD_OPTION,
    742         TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,
    743         TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,
    744         TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,
    745         TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper()       :   MODEL_PCD_DYNAMIC_DEFAULT,
    746         TAB_PCDS_DYNAMIC_HII_NULL.upper()           :   MODEL_PCD_DYNAMIC_HII,
    747         TAB_PCDS_DYNAMIC_VPD_NULL.upper()           :   MODEL_PCD_DYNAMIC_VPD,
    748         TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper()    :   MODEL_PCD_DYNAMIC_EX_DEFAULT,
    749         TAB_PCDS_DYNAMIC_EX_HII_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_HII,
    750         TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_VPD,
    751         TAB_COMPONENTS.upper()                      :   MODEL_META_DATA_COMPONENT,
    752         TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() :   MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
    753         TAB_DSC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,
    754         TAB_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,
    755         TAB_DSC_DEFINES_EDKGLOBAL                   :   MODEL_META_DATA_GLOBAL_DEFINE,
    756         TAB_INCLUDE.upper()                         :   MODEL_META_DATA_INCLUDE,
    757         TAB_IF.upper()                              :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
    758         TAB_IF_DEF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
    759         TAB_IF_N_DEF.upper()                        :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
    760         TAB_ELSE_IF.upper()                         :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
    761         TAB_ELSE.upper()                            :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
    762         TAB_END_IF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
    763         TAB_ERROR.upper()                           :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,
    764     }
    765 
    766     # Valid names in define section

    767     DefineKeywords = [
    768         "DSC_SPECIFICATION",
    769         "PLATFORM_NAME",
    770         "PLATFORM_GUID",
    771         "PLATFORM_VERSION",
    772         "SKUID_IDENTIFIER",
    773         "PCD_INFO_GENERATION",
    774         "SUPPORTED_ARCHITECTURES",
    775         "BUILD_TARGETS",
    776         "OUTPUT_DIRECTORY",
    777         "FLASH_DEFINITION",
    778         "BUILD_NUMBER",
    779         "RFC_LANGUAGES",
    780         "ISO_LANGUAGES",
    781         "TIME_STAMP_FILE",
    782         "VPD_TOOL_GUID",
    783         "FIX_LOAD_TOP_MEMORY_ADDRESS"
    784     ]
    785 
    786     SubSectionDefineKeywords = [
    787         "FILE_GUID"
    788     ]
    789 
    790     SymbolPattern = ValueExpression.SymbolPattern
    791 
    792     ## Constructor of DscParser

    793     #

    794     #  Initialize object of DscParser

    795     #

    796     #   @param      FilePath        The path of platform description file

    797     #   @param      FileType        The raw data of DSC file

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

    799     #   @param      Macros          Macros used for replacement in file

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

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

    802     #

    803     def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):
    804         # prevent re-initialization

    805         if hasattr(self, "_Table"):
    806             return
    807         MetaFileParser.__init__(self, FilePath, FileType, Table, Owner, From)
    808         self._Version = 0x00010005  # Only EDK2 dsc file is supported

    809         # to store conditional directive evaluation result

    810         self._DirectiveStack = []
    811         self._DirectiveEvalStack = []
    812         self._Enabled = 1
    813 
    814         # Final valid replacable symbols

    815         self._Symbols = {}
    816         #

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

    818         #  the owner item

    819         #

    820         self._IdMapping = {-1:-1}
    821         
    822         self.TblFile = EccGlobalData.gDb.TblFile
    823         self.FileID = -1
    824 
    825     ## Parser starter

    826     def Start(self):
    827         Content = ''
    828         try:
    829             Content = open(str(self.MetaFile.Path), 'r').readlines()
    830         except:
    831             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
    832         #

    833         # Insert a record for file

    834         #

    835         Filename = NormPath(self.MetaFile.Path)
    836         FileID = self.TblFile.GetFileId(Filename)
    837         if FileID:
    838             self.FileID = FileID
    839         else:
    840             self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC)
    841         
    842         
    843         for Index in range(0, len(Content)):
    844             Line = CleanString(Content[Index])
    845             # skip empty line

    846             if Line == '':
    847                 continue
    848 
    849             self._CurrentLine = Line
    850             self._LineIndex = Index
    851             if self._InSubsection and self._Owner[-1] == -1:
    852                 self._Owner.append(self._LastItem)
    853             
    854             # section header

    855             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
    856                 self._SectionType = MODEL_META_DATA_SECTION_HEADER
    857             # subsection ending

    858             elif Line[0] == '}' and self._InSubsection:
    859                 self._InSubsection = False
    860                 self._SubsectionType = MODEL_UNKNOWN
    861                 self._SubsectionName = ''
    862                 self._Owner[-1] = -1
    863                 continue
    864             # subsection header

    865             elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
    866                 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
    867             # directive line

    868             elif Line[0] == '!':
    869                 self._DirectiveParser()
    870                 continue
    871 
    872             if self._InSubsection:
    873                 SectionType = self._SubsectionType
    874             else:
    875                 SectionType = self._SectionType
    876             self._ItemType = SectionType
    877 
    878             self._ValueList = ['', '', '']
    879             self._SectionParser[SectionType](self)
    880             if self._ValueList == None:
    881                 continue
    882             #

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

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

    885             #

    886             for Arch, ModuleType in self._Scope:
    887                 self._LastItem = self._Store(
    888                                         self._ItemType,
    889                                         self._ValueList[0],
    890                                         self._ValueList[1],
    891                                         self._ValueList[2],
    892                                         Arch,
    893                                         ModuleType,
    894                                         self._Owner[-1],
    895                                         self.FileID,
    896                                         self._From,
    897                                         self._LineIndex+1,
    898                                         -1,
    899                                         self._LineIndex+1,
    900                                         -1,
    901                                         self._Enabled
    902                                         )
    903 
    904         if self._DirectiveStack:
    905             Type, Line, Text = self._DirectiveStack[-1]
    906             EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
    907                             ExtraData=Text, File=self.MetaFile, Line=Line)
    908         self._Done()
    909 
    910     ## <subsection_header> parser

    911     def _SubsectionHeaderParser(self):
    912         self._SubsectionName = self._CurrentLine[1:-1].upper()
    913         if self._SubsectionName in self.DataType:
    914             self._SubsectionType = self.DataType[self._SubsectionName]
    915         else:
    916             self._SubsectionType = MODEL_UNKNOWN
    917             EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
    918                            Line=self._LineIndex+1, ExtraData=self._CurrentLine)
    919         self._ValueList[0] = self._SubsectionName
    920 
    921     ## Directive statement parser

    922     def _DirectiveParser(self):
    923         self._ValueList = ['','','']
    924         TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
    925         self._ValueList[0:len(TokenList)] = TokenList
    926 
    927         # Syntax check

    928         DirectiveName = self._ValueList[0].upper()
    929         if DirectiveName not in self.DataType:
    930             EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
    931                             File=self.MetaFile, Line=self._LineIndex+1)
    932         if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
    933             EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
    934                             File=self.MetaFile, Line=self._LineIndex+1,
    935                             ExtraData=self._CurrentLine)
    936 
    937         ItemType = self.DataType[DirectiveName]
    938         if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
    939             # Remove all directives between !if and !endif, including themselves

    940             while self._DirectiveStack:
    941                 # Remove any !else or !elseif

    942                 DirectiveInfo = self._DirectiveStack.pop()
    943                 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
    944                                         MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
    945                                         MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
    946                     break
    947             else:
    948                 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
    949                                 File=self.MetaFile, Line=self._LineIndex+1,
    950                                 ExtraData=self._CurrentLine)
    951         elif ItemType != MODEL_META_DATA_INCLUDE:
    952             # Break if there's a !else is followed by a !elseif

    953             if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
    954                self._DirectiveStack and \
    955                self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
    956                 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
    957                                 File=self.MetaFile, Line=self._LineIndex+1,
    958                                 ExtraData=self._CurrentLine)
    959             self._DirectiveStack.append((ItemType, self._LineIndex+1, self._CurrentLine))
    960         elif self._From > 0:
    961             EdkLogger.error('Parser', FORMAT_INVALID,
    962                             "No '!include' allowed in included file",
    963                             ExtraData=self._CurrentLine, File=self.MetaFile, 
    964                             Line=self._LineIndex+1)
    965 
    966         #

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

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

    969         #

    970         self._LastItem = self._Store(
    971                                 ItemType,
    972                                 self._ValueList[0],
    973                                 self._ValueList[1],
    974                                 self._ValueList[2],
    975                                 'COMMON',
    976                                 'COMMON',
    977                                 self._Owner[-1],
    978                                 self.FileID,
    979                                 self._From,
    980                                 self._LineIndex+1,
    981                                 -1,
    982                                 self._LineIndex+1,
    983                                 -1,
    984                                 0
    985                                 )
    986 
    987     ## [defines] section parser

    988     @ParseMacro
    989     def _DefineParser(self):
    990         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
    991         self._ValueList[1:len(TokenList)] = TokenList
    992 
    993         # Syntax check

    994         if not self._ValueList[1]:
    995             EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
    996                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
    997         if not self._ValueList[2]:
    998             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
    999                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
   1000         if (not self._ValueList[1] in self.DefineKeywords and
   1001             (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):
   1002             EdkLogger.error('Parser', FORMAT_INVALID,
   1003                             "Unknown keyword found: %s. "
   1004                             "If this is a macro you must "
   1005                             "add it as a DEFINE in the DSC" % self._ValueList[1],
   1006                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
   1007         self._Defines[self._ValueList[1]] = self._ValueList[2]
   1008         self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
   1009 
   1010     @ParseMacro
   1011     def _SkuIdParser(self):
   1012         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
   1013         if len(TokenList) != 2:
   1014             EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",
   1015                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
   1016         self._ValueList[0:len(TokenList)] = TokenList
   1017 
   1018     ## Parse Edk style of library modules

   1019     def _LibraryInstanceParser(self):
   1020         self._ValueList[0] = self._CurrentLine
   1021 
   1022     ## PCD sections parser

   1023     #

   1024     #   [PcdsFixedAtBuild]

   1025     #   [PcdsPatchableInModule]

   1026     #   [PcdsFeatureFlag]

   1027     #   [PcdsDynamicEx

   1028     #   [PcdsDynamicExDefault]

   1029     #   [PcdsDynamicExVpd]

   1030     #   [PcdsDynamicExHii]

   1031     #   [PcdsDynamic]

   1032     #   [PcdsDynamicDefault]

   1033     #   [PcdsDynamicVpd]

   1034     #   [PcdsDynamicHii]

   1035     #

   1036     @ParseMacro
   1037     def _PcdParser(self):
   1038         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
   1039         self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
   1040         if len(TokenList) == 2:
   1041             self._ValueList[2] = TokenList[1]
   1042         if self._ValueList[0] == '' or self._ValueList[1] == '':
   1043             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
   1044                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
   1045                             File=self.MetaFile, Line=self._LineIndex+1)
   1046         if self._ValueList[2] == '':
   1047             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
   1048                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
   1049                             File=self.MetaFile, Line=self._LineIndex+1)
   1050         # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.

   1051         DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
   1052         if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
   1053             self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
   1054         elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
   1055             self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
   1056 
   1057     ## [components] section parser

   1058     @ParseMacro
   1059     def _ComponentParser(self):
   1060         if self._CurrentLine[-1] == '{':
   1061             self._ValueList[0] = self._CurrentLine[0:-1].strip()
   1062             self._InSubsection = True
   1063         else:
   1064             self._ValueList[0] = self._CurrentLine
   1065 
   1066     ## [LibraryClasses] section

   1067     @ParseMacro
   1068     def _LibraryClassParser(self):
   1069         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
   1070         if len(TokenList) < 2:
   1071             EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
   1072                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
   1073                             File=self.MetaFile, Line=self._LineIndex+1)
   1074         if TokenList[0] == '':
   1075             EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
   1076                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
   1077                             File=self.MetaFile, Line=self._LineIndex+1)
   1078         if TokenList[1] == '':
   1079             EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
   1080                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
   1081                             File=self.MetaFile, Line=self._LineIndex+1)
   1082 
   1083         self._ValueList[0:len(TokenList)] = TokenList
   1084 
   1085     def _CompponentSourceOverridePathParser(self):
   1086         self._ValueList[0] = self._CurrentLine
   1087 
   1088     ## [BuildOptions] section parser

   1089     @ParseMacro
   1090     def _BuildOptionParser(self):
   1091         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
   1092         TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
   1093         if len(TokenList2) == 2:
   1094             self._ValueList[0] = TokenList2[0]  # toolchain family

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

   1096         else:
   1097             self._ValueList[1] = TokenList[0]
   1098         if len(TokenList) == 2:                 # value

   1099             self._ValueList[2] = TokenList[1]
   1100 
   1101         if self._ValueList[1].count('_') != 4:
   1102             EdkLogger.error(
   1103                 'Parser',
   1104                 FORMAT_INVALID,
   1105                 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
   1106                 ExtraData=self._CurrentLine,
   1107                 File=self.MetaFile,
   1108                 Line=self._LineIndex+1
   1109                 )
   1110 
   1111     ## Override parent's method since we'll do all macro replacements in parser

   1112     def _GetMacros(self):
   1113         Macros = dict( [('ARCH','IA32'), ('FAMILY','MSFT'),('TOOL_CHAIN_TAG','VS2008x86'),('TARGET','DEBUG')])
   1114         Macros.update(self._FileLocalMacros)
   1115         Macros.update(self._GetApplicableSectionMacro())
   1116         Macros.update(GlobalData.gEdkGlobal)
   1117         Macros.update(GlobalData.gPlatformDefines)
   1118         Macros.update(GlobalData.gCommandLineDefines)
   1119         # PCD cannot be referenced in macro definition

   1120         if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
   1121             Macros.update(self._Symbols)
   1122         return Macros
   1123 
   1124     def _PostProcess(self):
   1125         Processer = {
   1126             MODEL_META_DATA_SECTION_HEADER                  :   self.__ProcessSectionHeader,
   1127             MODEL_META_DATA_SUBSECTION_HEADER               :   self.__ProcessSubsectionHeader,
   1128             MODEL_META_DATA_HEADER                          :   self.__ProcessDefine,
   1129             MODEL_META_DATA_DEFINE                          :   self.__ProcessDefine,
   1130             MODEL_META_DATA_GLOBAL_DEFINE                   :   self.__ProcessDefine,
   1131             MODEL_META_DATA_INCLUDE                         :   self.__ProcessDirective,
   1132             MODEL_META_DATA_CONDITIONAL_STATEMENT_IF        :   self.__ProcessDirective,
   1133             MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE      :   self.__ProcessDirective,
   1134             MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF     :   self.__ProcessDirective,
   1135             MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF    :   self.__ProcessDirective,
   1136             MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF     :   self.__ProcessDirective,
   1137             MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF    :   self.__ProcessDirective,
   1138             MODEL_EFI_SKU_ID                                :   self.__ProcessSkuId,
   1139             MODEL_EFI_LIBRARY_INSTANCE                      :   self.__ProcessLibraryInstance,
   1140             MODEL_EFI_LIBRARY_CLASS                         :   self.__ProcessLibraryClass,
   1141             MODEL_PCD_FIXED_AT_BUILD                        :   self.__ProcessPcd,
   1142             MODEL_PCD_PATCHABLE_IN_MODULE                   :   self.__ProcessPcd,
   1143             MODEL_PCD_FEATURE_FLAG                          :   self.__ProcessPcd,
   1144             MODEL_PCD_DYNAMIC_DEFAULT                       :   self.__ProcessPcd,
   1145             MODEL_PCD_DYNAMIC_HII                           :   self.__ProcessPcd,
   1146             MODEL_PCD_DYNAMIC_VPD                           :   self.__ProcessPcd,
   1147             MODEL_PCD_DYNAMIC_EX_DEFAULT                    :   self.__ProcessPcd,
   1148             MODEL_PCD_DYNAMIC_EX_HII                        :   self.__ProcessPcd,
   1149             MODEL_PCD_DYNAMIC_EX_VPD                        :   self.__ProcessPcd,
   1150             MODEL_META_DATA_COMPONENT                       :   self.__ProcessComponent,
   1151             MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH  :   self.__ProcessSourceOverridePath,
   1152             MODEL_META_DATA_BUILD_OPTION                    :   self.__ProcessBuildOption,
   1153             MODEL_UNKNOWN                                   :   self._Skip,
   1154             MODEL_META_DATA_USER_EXTENSION                  :   self._Skip,
   1155             MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR     :   self._Skip,
   1156         }
   1157         
   1158         self._RawTable = self._Table
   1159         self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)
   1160         self._DirectiveStack = []
   1161         self._DirectiveEvalStack = []
   1162         self._FileWithError = self.MetaFile
   1163         self._FileLocalMacros = {}
   1164         self._SectionsMacroDict = {}
   1165         GlobalData.gPlatformDefines = {}
   1166 
   1167         # Get all macro and PCD which has straitforward value

   1168         self.__RetrievePcdValue()
   1169         self._Content = self._RawTable.GetAll()
   1170         self._ContentIndex = 0
   1171         while self._ContentIndex < len(self._Content) :
   1172             Id, self._ItemType, V1, V2, V3, S1, S2, Owner, BelongsToFile, self._From, \
   1173                 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
   1174 
   1175             if self._From < 0:
   1176                 self._FileWithError = self.MetaFile
   1177 
   1178             self._ContentIndex += 1
   1179 
   1180             self._Scope = [[S1, S2]]
   1181             self._LineIndex = LineStart - 1
   1182             self._ValueList = [V1, V2, V3]
   1183 
   1184             try:
   1185                 Processer[self._ItemType]()
   1186             except EvaluationException, Excpt:
   1187                 # 

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

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

   1190                 #

   1191                 pass
   1192 #                 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),

   1193 #                                 File=self._FileWithError, ExtraData=' '.join(self._ValueList),

   1194 #                                 Line=self._LineIndex+1)

   1195             except MacroException, Excpt:
   1196                 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
   1197                                 File=self._FileWithError, ExtraData=' '.join(self._ValueList), 
   1198                                 Line=self._LineIndex+1)
   1199 
   1200             if self._ValueList == None:
   1201                 continue 
   1202 
   1203             NewOwner = self._IdMapping.get(Owner, -1)
   1204             self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
   1205             self._LastItem = self._Store(
   1206                                 self._ItemType,
   1207                                 self._ValueList[0],
   1208                                 self._ValueList[1],
   1209                                 self._ValueList[2],
   1210                                 S1,
   1211                                 S2,
   1212                                 NewOwner,
   1213                                 BelongsToFile,
   1214                                 self._From,
   1215                                 self._LineIndex+1,
   1216                                 -1,
   1217                                 self._LineIndex+1,
   1218                                 -1,
   1219                                 self._Enabled
   1220                                 )
   1221             self._IdMapping[Id] = self._LastItem
   1222 
   1223         RecordList = self._Table.GetAll()
   1224         
   1225         self._RawTable.Drop()
   1226         self._Table.Drop()
   1227         for Record in RecordList:
   1228             EccGlobalData.gDb.TblDsc.Insert(Record[1],Record[2],Record[3],Record[4],Record[5],Record[6],Record[7],Record[8],Record[9],Record[10],Record[11],Record[12],Record[13],Record[14])
   1229         GlobalData.gPlatformDefines.update(self._FileLocalMacros)
   1230         self._PostProcessed = True
   1231         self._Content = None
   1232 
   1233     def __ProcessSectionHeader(self):
   1234         self._SectionName = self._ValueList[0]
   1235         if self._SectionName in self.DataType:
   1236             self._SectionType = self.DataType[self._SectionName]
   1237         else:
   1238             self._SectionType = MODEL_UNKNOWN
   1239 
   1240     def __ProcessSubsectionHeader(self):
   1241         self._SubsectionName = self._ValueList[0]
   1242         if self._SubsectionName in self.DataType:
   1243             self._SubsectionType = self.DataType[self._SubsectionName]
   1244         else:
   1245             self._SubsectionType = MODEL_UNKNOWN
   1246 
   1247     def __RetrievePcdValue(self):
   1248         Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0)
   1249         for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:
   1250             Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
   1251             # Only use PCD whose value is straitforward (no macro and PCD)

   1252             if self.SymbolPattern.findall(Value):
   1253                 continue
   1254             Name = TokenSpaceGuid + '.' + PcdName
   1255             # Don't use PCD with different values.

   1256             if Name in self._Symbols and self._Symbols[Name] != Value:
   1257                 self._Symbols.pop(Name)
   1258                 continue 
   1259             self._Symbols[Name] = Value
   1260 
   1261         Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0)
   1262         for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:
   1263             Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
   1264             # Only use PCD whose value is straitforward (no macro and PCD)

   1265             if self.SymbolPattern.findall(Value):
   1266                 continue 
   1267             Name = TokenSpaceGuid+'.'+PcdName
   1268             # Don't use PCD with different values.

   1269             if Name in self._Symbols and self._Symbols[Name] != Value:
   1270                 self._Symbols.pop(Name)
   1271                 continue 
   1272             self._Symbols[Name] = Value
   1273 
   1274     def __ProcessDefine(self):
   1275         if not self._Enabled:
   1276             return
   1277 
   1278         Type, Name, Value = self._ValueList
   1279         Value = ReplaceMacro(Value, self._Macros, False)
   1280         if self._ItemType == MODEL_META_DATA_DEFINE:
   1281             if self._SectionType == MODEL_META_DATA_HEADER:
   1282                 self._FileLocalMacros[Name] = Value
   1283             else:
   1284                 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
   1285                 if SectionDictKey not in self._SectionsMacroDict:
   1286                     self._SectionsMacroDict[SectionDictKey] = {}
   1287                 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
   1288                 SectionLocalMacros[Name] = Value
   1289         elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
   1290             GlobalData.gEdkGlobal[Name] = Value
   1291         
   1292         #

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

   1294         #

   1295         if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
   1296             self._FileLocalMacros[Name] = Value
   1297             
   1298         self._ValueList = [Type, Name, Value]
   1299 
   1300     def __ProcessDirective(self):
   1301         Result = None
   1302         if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
   1303                               MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
   1304             Macros = self._Macros
   1305             Macros.update(GlobalData.gGlobalDefines)
   1306             try:
   1307                 Result = ValueExpression(self._ValueList[1], Macros)()
   1308             except SymbolNotFound, Exc:
   1309                 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
   1310                 Result = False
   1311             except WrnExpression, Excpt:
   1312                 # 

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

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

   1315                 #

   1316                 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
   1317                                 File=self._FileWithError, ExtraData=' '.join(self._ValueList), 
   1318                                 Line=self._LineIndex+1)
   1319                 Result = Excpt.result
   1320             except BadExpression, Exc:
   1321                 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
   1322                 Result = False
   1323 
   1324         if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
   1325                               MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
   1326                               MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
   1327             self._DirectiveStack.append(self._ItemType)
   1328             if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
   1329                 Result = bool(Result)
   1330             else:
   1331                 Macro = self._ValueList[1]
   1332                 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
   1333                 Result = Macro in self._Macros
   1334                 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
   1335                     Result = not Result
   1336             self._DirectiveEvalStack.append(Result)
   1337         elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
   1338             self._DirectiveStack.append(self._ItemType)
   1339             self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
   1340             self._DirectiveEvalStack.append(bool(Result))
   1341         elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
   1342             self._DirectiveStack[-1] = self._ItemType
   1343             self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
   1344         elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
   1345             # Back to the nearest !if/!ifdef/!ifndef

   1346             while self._DirectiveStack:
   1347                 self._DirectiveEvalStack.pop()
   1348                 Directive = self._DirectiveStack.pop()
   1349                 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
   1350                                  MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
   1351                                  MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
   1352                                  MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
   1353                     break
   1354         elif self._ItemType == MODEL_META_DATA_INCLUDE:
   1355             # The included file must be relative to workspace or same directory as DSC file

   1356             __IncludeMacros = {}
   1357             #

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

   1359             #

   1360             __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
   1361             if "ECP_SOURCE" in GlobalData.gGlobalDefines.keys():
   1362                 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']
   1363             #

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

   1365             #

   1366             elif "ECP_SOURCE" in GlobalData.gCommandLineDefines.keys():
   1367                 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']
   1368                 
   1369             __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']
   1370             __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']
   1371             #

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

   1373             #

   1374             __IncludeMacros.update(self._Macros)
   1375             
   1376             IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
   1377             #

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

   1379             #

   1380             IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
   1381             ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
   1382             if ErrorCode != 0:
   1383                 #

   1384                 # Also search file under the WORKSPACE directory

   1385                 #

   1386                 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
   1387                 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
   1388                 if ErrorCode != 0:
   1389                     EdkLogger.error('parser', ErrorCode, File=self._FileWithError, 
   1390                                     Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2)
   1391 
   1392             self._FileWithError = IncludedFile1
   1393 
   1394             IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True)
   1395             Owner = self._Content[self._ContentIndex-1][0]
   1396             Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable, 
   1397                                Owner=Owner, From=Owner)
   1398 
   1399             # set the parser status with current status

   1400             Parser._SectionName = self._SectionName
   1401             Parser._SectionType = self._SectionType
   1402             Parser._Scope = self._Scope
   1403             Parser._Enabled = self._Enabled
   1404             # Parse the included file

   1405             Parser.Start()
   1406 
   1407             # update current status with sub-parser's status

   1408             self._SectionName = Parser._SectionName
   1409             self._SectionType = Parser._SectionType
   1410             self._Scope       = Parser._Scope
   1411             self._Enabled     = Parser._Enabled
   1412 
   1413             # Insert all records in the table for the included file into dsc file table

   1414             Records = IncludedFileTable.GetAll()
   1415             if Records:
   1416                 self._Content[self._ContentIndex:self._ContentIndex] = Records
   1417                 self._Content.pop(self._ContentIndex-1)
   1418                 self._ValueList = None
   1419                 self._ContentIndex -= 1
   1420                 
   1421     def __ProcessSkuId(self):
   1422         self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
   1423                            for Value in self._ValueList]
   1424 
   1425     def __ProcessLibraryInstance(self):
   1426         self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
   1427 
   1428     def __ProcessLibraryClass(self):
   1429         self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
   1430 
   1431     def __ProcessPcd(self):
   1432         ValueList = GetSplitValueList(self._ValueList[2])
   1433         #

   1434         # PCD value can be an expression

   1435         #

   1436         if len(ValueList) > 1 and ValueList[1] == 'VOID*':
   1437             PcdValue = ValueList[0]      
   1438             try:
   1439                 ValueList[0] = ValueExpression(PcdValue, self._Macros)(True)
   1440             except WrnExpression, Value:
   1441                 ValueList[0] = Value.result          
   1442         else:
   1443             PcdValue = ValueList[-1]
   1444             try:
   1445                 ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True)
   1446             except WrnExpression, Value:
   1447                 ValueList[-1] = Value.result
   1448             
   1449             if ValueList[-1] == 'True':
   1450                 ValueList[-1] = '1'
   1451             if ValueList[-1] == 'False':
   1452                 ValueList[-1] = '0'      
   1453 
   1454         self._ValueList[2] = '|'.join(ValueList)
   1455 
   1456     def __ProcessComponent(self):
   1457         self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
   1458 
   1459     def __ProcessSourceOverridePath(self):
   1460         self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
   1461 
   1462     def __ProcessBuildOption(self):
   1463         self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
   1464                            for Value in self._ValueList]
   1465 
   1466     _SectionParser = {
   1467         MODEL_META_DATA_HEADER                          :   _DefineParser,
   1468         MODEL_EFI_SKU_ID                                :   _SkuIdParser,
   1469         MODEL_EFI_LIBRARY_INSTANCE                      :   _LibraryInstanceParser,
   1470         MODEL_EFI_LIBRARY_CLASS                         :   _LibraryClassParser,
   1471         MODEL_PCD_FIXED_AT_BUILD                        :   _PcdParser,
   1472         MODEL_PCD_PATCHABLE_IN_MODULE                   :   _PcdParser,
   1473         MODEL_PCD_FEATURE_FLAG                          :   _PcdParser,
   1474         MODEL_PCD_DYNAMIC_DEFAULT                       :   _PcdParser,
   1475         MODEL_PCD_DYNAMIC_HII                           :   _PcdParser,
   1476         MODEL_PCD_DYNAMIC_VPD                           :   _PcdParser,
   1477         MODEL_PCD_DYNAMIC_EX_DEFAULT                    :   _PcdParser,
   1478         MODEL_PCD_DYNAMIC_EX_HII                        :   _PcdParser,
   1479         MODEL_PCD_DYNAMIC_EX_VPD                        :   _PcdParser,
   1480         MODEL_META_DATA_COMPONENT                       :   _ComponentParser,
   1481         MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH  :   _CompponentSourceOverridePathParser,
   1482         MODEL_META_DATA_BUILD_OPTION                    :   _BuildOptionParser,
   1483         MODEL_UNKNOWN                                   :   MetaFileParser._Skip,
   1484         MODEL_META_DATA_USER_EXTENSION                  :   MetaFileParser._Skip,
   1485         MODEL_META_DATA_SECTION_HEADER                  :   MetaFileParser._SectionHeaderParser,
   1486         MODEL_META_DATA_SUBSECTION_HEADER               :   _SubsectionHeaderParser,
   1487     }
   1488 
   1489     _Macros     = property(_GetMacros)
   1490 
   1491 ## DEC file parser class

   1492 #

   1493 #   @param      FilePath        The path of platform description file

   1494 #   @param      FileType        The raw data of DSC file

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

   1496 #   @param      Macros          Macros used for replacement in file

   1497 #

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

   1500     DataType = {
   1501         TAB_DEC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,
   1502         TAB_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,
   1503         TAB_INCLUDES.upper()                        :   MODEL_EFI_INCLUDE,
   1504         TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,
   1505         TAB_GUIDS.upper()                           :   MODEL_EFI_GUID,
   1506         TAB_PPIS.upper()                            :   MODEL_EFI_PPI,
   1507         TAB_PROTOCOLS.upper()                       :   MODEL_EFI_PROTOCOL,
   1508         TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,
   1509         TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,
   1510         TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,
   1511         TAB_PCDS_DYNAMIC_NULL.upper()               :   MODEL_PCD_DYNAMIC,
   1512         TAB_PCDS_DYNAMIC_EX_NULL.upper()            :   MODEL_PCD_DYNAMIC_EX,
   1513     }
   1514 
   1515     ## Constructor of DecParser

   1516     #

   1517     #  Initialize object of DecParser

   1518     #

   1519     #   @param      FilePath        The path of platform description file

   1520     #   @param      FileType        The raw data of DSC file

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

   1522     #   @param      Macros          Macros used for replacement in file

   1523     #

   1524     def __init__(self, FilePath, FileType, Table):
   1525         # prevent re-initialization

   1526         if hasattr(self, "_Table"):
   1527             return
   1528         MetaFileParser.__init__(self, FilePath, FileType, Table)
   1529         self._Comments = []
   1530         self._Version = 0x00010005  # Only EDK2 dec file is supported

   1531         self.TblFile = EccGlobalData.gDb.TblFile
   1532         self.FileID = -1
   1533 
   1534     ## Parser starter

   1535     def Start(self):
   1536         Content = ''
   1537         try:
   1538             Content = open(str(self.MetaFile), 'r').readlines()
   1539         except:
   1540             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
   1541 
   1542         #

   1543         # Insert a record for file

   1544         #

   1545         Filename = NormPath(self.MetaFile)
   1546         FileID = self.TblFile.GetFileId(Filename)
   1547         if FileID:
   1548             self.FileID = FileID
   1549         else:
   1550             self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC)
   1551         
   1552         for Index in range(0, len(Content)):
   1553             Line, Comment = CleanString2(Content[Index])
   1554             self._CurrentLine = Line
   1555             self._LineIndex = Index
   1556 
   1557             # save comment for later use

   1558             if Comment:
   1559                 self._Comments.append((Comment, self._LineIndex+1))
   1560             # skip empty line

   1561             if Line == '':
   1562                 continue
   1563 
   1564             # section header

   1565             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
   1566                 self._SectionHeaderParser()
   1567                 self._Comments = []
   1568                 continue
   1569             elif len(self._SectionType) == 0:
   1570                 self._Comments = []
   1571                 continue
   1572 
   1573             # section content

   1574             self._ValueList = ['','','']
   1575             self._SectionParser[self._SectionType[0]](self)
   1576             if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
   1577                 self._ItemType = -1
   1578                 self._Comments = []
   1579                 continue
   1580 
   1581             #

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

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

   1584             #

   1585             for Arch, ModuleType, Type in self._Scope:
   1586                 self._LastItem = self._Store(
   1587                     Type,
   1588                     self._ValueList[0],
   1589                     self._ValueList[1],
   1590                     self._ValueList[2],
   1591                     Arch,
   1592                     ModuleType,
   1593                     self._Owner[-1],
   1594                     self.FileID,
   1595                     self._LineIndex+1,
   1596                     -1,
   1597                     self._LineIndex+1,
   1598                     -1,
   1599                     0
   1600                     )
   1601                 for Comment, LineNo in self._Comments:
   1602                     self._Store(
   1603                         MODEL_META_DATA_COMMENT,
   1604                         Comment,
   1605                         self._ValueList[0],
   1606                         self._ValueList[1],
   1607                         Arch,
   1608                         ModuleType,
   1609                         self._LastItem,
   1610                         self.FileID,
   1611                         LineNo,
   1612                         -1,
   1613                         LineNo,
   1614                         -1,
   1615                         0
   1616                         )
   1617             self._Comments = []
   1618         self._Done()
   1619 
   1620     def _GetApplicableSectionMacro(self):
   1621         Macros = {}
   1622         for S1, S2, SectionType in self._Scope:
   1623             for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", S2), (S1, "COMMON"), (S1, S2)]:
   1624                 if (SectionType, Scope1, Scope2) in self._SectionsMacroDict:
   1625                     Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)])
   1626         return Macros
   1627 
   1628     ## Section header parser

   1629     #

   1630     #   The section header is always in following format:

   1631     #

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

   1633     #

   1634     def _SectionHeaderParser(self):
   1635         self._Scope = []
   1636         self._SectionName = ''
   1637         self._SectionType = []
   1638         ArchList = set()
   1639         for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
   1640             if Item == '':
   1641                 continue
   1642             ItemList = GetSplitValueList(Item, TAB_SPLIT)
   1643 
   1644             # different types of PCD are permissible in one section

   1645             self._SectionName = ItemList[0].upper()
   1646             if self._SectionName in self.DataType:
   1647                 if self.DataType[self._SectionName] not in self._SectionType:
   1648                     self._SectionType.append(self.DataType[self._SectionName])
   1649             else:
   1650                 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
   1651                                 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
   1652                 continue
   1653 
   1654             if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
   1655                 EdkLogger.error(
   1656                             'Parser',
   1657                             FORMAT_INVALID,
   1658                             "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
   1659                             File=self.MetaFile,
   1660                             Line=self._LineIndex+1,
   1661                             ExtraData=self._CurrentLine
   1662                             )
   1663             # S1 is always Arch

   1664             if len(ItemList) > 1:
   1665                 S1 = ItemList[1].upper()
   1666             else:
   1667                 S1 = 'COMMON'
   1668             ArchList.add(S1)
   1669             # S2 may be Platform or ModuleType

   1670             if len(ItemList) > 2:
   1671                 S2 = ItemList[2].upper()
   1672             else:
   1673                 S2 = 'COMMON'
   1674             if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
   1675                 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
   1676 
   1677         # 'COMMON' must not be used with specific ARCHs at the same section

   1678         if 'COMMON' in ArchList and len(ArchList) > 1:
   1679             EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
   1680                             File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
   1681 
   1682     ## [guids], [ppis] and [protocols] section parser

   1683     @ParseMacro
   1684     def _GuidParser(self):
   1685         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
   1686         if len(TokenList) < 2:
   1687             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
   1688                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
   1689                             File=self.MetaFile, Line=self._LineIndex+1)
   1690         if TokenList[0] == '':
   1691             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
   1692                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
   1693                             File=self.MetaFile, Line=self._LineIndex+1)
   1694         if TokenList[1] == '':
   1695             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
   1696                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
   1697                             File=self.MetaFile, Line=self._LineIndex+1)
   1698         if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
   1699             EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
   1700                             ExtraData=self._CurrentLine + \
   1701                                       " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
   1702                             File=self.MetaFile, Line=self._LineIndex+1)
   1703         self._ValueList[0] = TokenList[0]
   1704         #Parse the Guid value format

   1705         GuidValueList = TokenList[1].strip(' {}').split(',')
   1706         Index = 0
   1707         HexList = []
   1708         if len(GuidValueList) == 11:
   1709             for GuidValue in GuidValueList:
   1710                 GuidValue = GuidValue.strip()
   1711                 if GuidValue.startswith('0x') or GuidValue.startswith('0X'):
   1712                     HexList.append('0x' + str(GuidValue[2:]))
   1713                     Index += 1
   1714                     continue
   1715                 else:
   1716                     if GuidValue.startswith('{'):
   1717                         GuidValue = GuidValue.lstrip(' {')
   1718                         HexList.append('0x' + str(GuidValue[2:]))
   1719                         Index += 1
   1720             self._ValueList[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList[0], HexList[1], HexList[2],HexList[3],HexList[4],HexList[5],HexList[6],HexList[7],HexList[8],HexList[9],HexList[10])
   1721         else:
   1722             EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
   1723                             ExtraData=self._CurrentLine + \
   1724                                       " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
   1725                             File=self.MetaFile, Line=self._LineIndex+1)
   1726             self._ValueList[0] = ''
   1727 
   1728     ## PCD sections parser

   1729     #

   1730     #   [PcdsFixedAtBuild]

   1731     #   [PcdsPatchableInModule]

   1732     #   [PcdsFeatureFlag]

   1733     #   [PcdsDynamicEx

   1734     #   [PcdsDynamic]

   1735     #

   1736     @ParseMacro
   1737     def _PcdParser(self):
   1738         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
   1739         self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
   1740         # check PCD information

   1741         if self._ValueList[0] == '' or self._ValueList[1] == '':
   1742             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
   1743                             ExtraData=self._CurrentLine + \
   1744                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1745                             File=self.MetaFile, Line=self._LineIndex+1)
   1746         # check PCD datum information

   1747         if len(TokenList) < 2 or TokenList[1] == '':
   1748             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
   1749                             ExtraData=self._CurrentLine + \
   1750                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1751                             File=self.MetaFile, Line=self._LineIndex+1)
   1752 
   1753         
   1754         ValueRe  = re.compile(r'^\s*L?\".*\|.*\"')
   1755         PtrValue = ValueRe.findall(TokenList[1])
   1756         
   1757         # Has VOID* type string, may contain "|" character in the string. 

   1758         if len(PtrValue) != 0:
   1759             ptrValueList = re.sub(ValueRe, '', TokenList[1])
   1760             ValueList    = GetSplitValueList(ptrValueList)
   1761             ValueList[0] = PtrValue[0]
   1762         else:
   1763             ValueList = GetSplitValueList(TokenList[1])
   1764             
   1765         
   1766         # check if there's enough datum information given

   1767         if len(ValueList) != 3:
   1768             EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
   1769                             ExtraData=self._CurrentLine + \
   1770                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1771                             File=self.MetaFile, Line=self._LineIndex+1)
   1772         # check default value

   1773         if ValueList[0] == '':
   1774             EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
   1775                             ExtraData=self._CurrentLine + \
   1776                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1777                             File=self.MetaFile, Line=self._LineIndex+1)
   1778         # check datum type

   1779         if ValueList[1] == '':
   1780             EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
   1781                             ExtraData=self._CurrentLine + \
   1782                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1783                             File=self.MetaFile, Line=self._LineIndex+1)
   1784         # check token of the PCD

   1785         if ValueList[2] == '':
   1786             EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
   1787                             ExtraData=self._CurrentLine + \
   1788                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
   1789                             File=self.MetaFile, Line=self._LineIndex+1)
   1790         # check format of default value against the datum type

   1791         IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
   1792         if not IsValid:
   1793             EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
   1794                             File=self.MetaFile, Line=self._LineIndex+1)
   1795         
   1796         if EccGlobalData.gConfig.UniCheckPCDInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
   1797             # check Description, Prompt information

   1798             PatternDesc = re.compile('##\s*([\x21-\x7E\s]*)', re.S)
   1799             PatternPrompt = re.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re.S)
   1800             Description = None
   1801             Prompt = None
   1802             # check @ValidRange, @ValidList and @Expression format valid

   1803             ErrorCodeValid = '0x0 <= %s <= 0xFFFFFFFF'
   1804             PatternValidRangeIn = '(NOT)?\s*(\d+\s*-\s*\d+|0[xX][a-fA-F0-9]+\s*-\s*0[xX][a-fA-F0-9]+|LT\s*\d+|LT\s*0[xX][a-fA-F0-9]+|GT\s*\d+|GT\s*0[xX][a-fA-F0-9]+|LE\s*\d+|LE\s*0[xX][a-fA-F0-9]+|GE\s*\d+|GE\s*0[xX][a-fA-F0-9]+|XOR\s*\d+|XOR\s*0[xX][a-fA-F0-9]+|EQ\s*\d+|EQ\s*0[xX][a-fA-F0-9]+)'
   1805             PatternValidRng = re.compile('^' + '(NOT)?\s*' + PatternValidRangeIn + '$')
   1806             for Comment in self._Comments:
   1807                 Comm = Comment[0].strip()
   1808                 if not Comm:
   1809                     continue
   1810                 if not Description:
   1811                     Description = PatternDesc.findall(Comm)
   1812                 if not Prompt:
   1813                     Prompt = PatternPrompt.findall(Comm)
   1814                 if Comm[0] == '#':
   1815                     ValidFormt = Comm.lstrip('#')
   1816                     ValidFormt = ValidFormt.lstrip()
   1817                     if ValidFormt[0:11] == '@ValidRange':
   1818                         ValidFormt = ValidFormt[11:]
   1819                         ValidFormt = ValidFormt.lstrip()
   1820                         try:
   1821                             ErrorCode, Expression = ValidFormt.split('|', 1)
   1822                         except ValueError:
   1823                             ErrorCode = '0x0'
   1824                             Expression = ValidFormt
   1825                         ErrorCode, Expression = ErrorCode.strip(), Expression.strip()
   1826                         try:
   1827                             if not eval(ErrorCodeValid % ErrorCode):
   1828                                 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
   1829                         except:
   1830                             EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
   1831                         if not PatternValidRng.search(Expression):
   1832                             EdkLogger.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression, TokenList[0]))
   1833                     if ValidFormt[0:10] == '@ValidList':
   1834                         ValidFormt = ValidFormt[10:]
   1835                         ValidFormt = ValidFormt.lstrip()
   1836                         try:
   1837                             ErrorCode, Expression = ValidFormt.split('|', 1)
   1838                         except ValueError:
   1839                             ErrorCode = '0x0'
   1840                             Expression = ValidFormt
   1841                         ErrorCode, Expression = ErrorCode.strip(), Expression.strip()
   1842                         try:
   1843                             if not eval(ErrorCodeValid % ErrorCode):
   1844                                 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
   1845                         except:
   1846                             EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
   1847                         Values = Expression.split(',')
   1848                         for Value in Values:
   1849                             Value = Value.strip()
   1850                             try:
   1851                                 eval(Value)
   1852                             except:
   1853                                 EdkLogger.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList[0], Value))
   1854                                 break
   1855                     if ValidFormt[0:11] == '@Expression':
   1856                         ValidFormt = ValidFormt[11:]
   1857                         ValidFormt = ValidFormt.lstrip()
   1858                         try:
   1859                             ErrorCode, Expression = ValidFormt.split('|', 1)
   1860                         except ValueError:
   1861                             ErrorCode = '0x0'
   1862                             Expression = ValidFormt
   1863                         ErrorCode, Expression = ErrorCode.strip(), Expression.strip()
   1864                         try:
   1865                             if not eval(ErrorCodeValid % ErrorCode):
   1866                                 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
   1867                         except:
   1868                             EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
   1869                         if not Expression:
   1870                             EdkLogger.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList[0])
   1871             if not Description:
   1872                 EdkLogger.warn('Parser', 'PCD %s Description information is not provided.' % TokenList[0])
   1873             if not Prompt:
   1874                 EdkLogger.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList[0])
   1875             # check Description, Prompt localization information

   1876             if self._UniObj:
   1877                 self._UniObj.CheckPcdInfo(TokenList[0])
   1878 
   1879         if ValueList[0] in ['True', 'true', 'TRUE']:
   1880             ValueList[0] = '1'
   1881         elif ValueList[0] in ['False', 'false', 'FALSE']:
   1882             ValueList[0] = '0'
   1883 
   1884         self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
   1885 
   1886     _SectionParser = {
   1887         MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,
   1888         MODEL_EFI_INCLUDE               :   MetaFileParser._PathParser,
   1889         MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,
   1890         MODEL_EFI_GUID                  :   _GuidParser,
   1891         MODEL_EFI_PPI                   :   _GuidParser,
   1892         MODEL_EFI_PROTOCOL              :   _GuidParser,
   1893         MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,
   1894         MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,
   1895         MODEL_PCD_FEATURE_FLAG          :   _PcdParser,
   1896         MODEL_PCD_DYNAMIC               :   _PcdParser,
   1897         MODEL_PCD_DYNAMIC_EX            :   _PcdParser,
   1898         MODEL_UNKNOWN                   :   MetaFileParser._Skip,
   1899         MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._Skip,
   1900     }
   1901 
   1902 
   1903 ## FdfObject

   1904 #

   1905 # This class defined basic Fdf object which is used by inheriting

   1906 # 

   1907 # @param object:       Inherited from object class

   1908 #

   1909 class FdfObject(object):
   1910     def __init__(self):
   1911         object.__init__()
   1912 
   1913 ## Fdf

   1914 #

   1915 # This class defined the structure used in Fdf object

   1916 # 

   1917 # @param FdfObject:     Inherited from FdfObject class

   1918 # @param Filename:      Input value for Ffilename of Fdf file, default is None

   1919 # @param WorkspaceDir:  Input value for current workspace directory, default is None

   1920 #

   1921 class Fdf(FdfObject):
   1922     def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None):
   1923         self.WorkspaceDir = WorkspaceDir
   1924         self.IsToDatabase = IsToDatabase
   1925         
   1926         self.Cur = Database.Cur
   1927         self.TblFile = Database.TblFile
   1928         self.TblFdf = Database.TblFdf
   1929         self.FileID = -1
   1930         self.FileList = {}
   1931 
   1932         #

   1933         # Load Fdf file if filename is not None

   1934         #

   1935         if Filename != None:
   1936             try:
   1937                 self.LoadFdfFile(Filename)
   1938             except Exception:
   1939                 pass
   1940 
   1941     #

   1942     # Insert a FDF file record into database

   1943     #

   1944     def InsertFile(self, Filename):
   1945         FileID = -1
   1946         Filename = NormPath(Filename)
   1947         if Filename not in self.FileList:
   1948             FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF)
   1949             self.FileList[Filename] = FileID
   1950 
   1951         return self.FileList[Filename]
   1952             
   1953     
   1954     ## Load Fdf file

   1955     #

   1956     # Load the file if it exists

   1957     #

   1958     # @param Filename:  Input value for filename of Fdf file

   1959     #

   1960     def LoadFdfFile(self, Filename):     
   1961         FileList = []
   1962         #

   1963         # Parse Fdf file

   1964         #

   1965         Filename = NormPath(Filename)
   1966         Fdf = FdfParser(Filename)
   1967         Fdf.ParseFile()
   1968 
   1969         #

   1970         # Insert inf file and pcd information

   1971         #

   1972         if self.IsToDatabase:
   1973             (Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \
   1974             (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
   1975             for Index in range(0, len(Fdf.Profile.PcdDict)):
   1976                 pass
   1977             for Key in Fdf.Profile.PcdDict.keys():
   1978                 Model = MODEL_PCD
   1979                 Value1 = Key[1]
   1980                 Value2 = Key[0]
   1981                 FileName = Fdf.Profile.PcdFileLineDict[Key][0]
   1982                 StartLine = Fdf.Profile.PcdFileLineDict[Key][1]
   1983                 BelongsToFile = self.InsertFile(FileName)
   1984                 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
   1985             for Index in range(0, len(Fdf.Profile.InfList)):
   1986                 Model = MODEL_META_DATA_COMPONENT
   1987                 Value1 = Fdf.Profile.InfList[Index]
   1988                 Value2 = ''
   1989                 FileName = Fdf.Profile.InfFileLineList[Index][0]
   1990                 StartLine = Fdf.Profile.InfFileLineList[Index][1]
   1991                 BelongsToFile = self.InsertFile(FileName)
   1992                 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
   1993 
   1994 class UniParser(object):
   1995     # IsExtraUni defined the UNI file is Module UNI or extra Module UNI

   1996     # IsModuleUni defined the UNI file is Module UNI or Package UNI

   1997     def __init__(self, FilePath, IsExtraUni=False, IsModuleUni=True):
   1998         self.FilePath = FilePath
   1999         self.FileName = os.path.basename(FilePath)
   2000         self.IsExtraUni = IsExtraUni
   2001         self.IsModuleUni = IsModuleUni
   2002         self.FileIn = None
   2003         self.Missing = []
   2004         self.__read()
   2005     
   2006     def __read(self):
   2007         try:
   2008             self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_8').read()
   2009         except UnicodeError:
   2010             self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16').read()
   2011         except UnicodeError:
   2012             self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16_le').read()
   2013         except IOError:
   2014             self.FileIn = ""
   2015     
   2016     def Start(self):
   2017         if self.IsModuleUni:
   2018             if self.IsExtraUni:
   2019                 ModuleName = self.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
   2020                 self.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName)
   2021             else:
   2022                 ModuleAbstract = self.CheckKeyValid('STR_MODULE_ABSTRACT')
   2023                 self.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract)
   2024                 ModuleDescription = self.CheckKeyValid('STR_MODULE_DESCRIPTION')
   2025                 self.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription)
   2026         else:
   2027             if self.IsExtraUni:
   2028                 PackageName = self.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
   2029                 self.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName)
   2030             else:
   2031                 PackageAbstract = self.CheckKeyValid('STR_PACKAGE_ABSTRACT')
   2032                 self.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract)
   2033                 PackageDescription = self.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
   2034                 self.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription)
   2035                 
   2036     def CheckKeyValid(self, Key, Contents=None):
   2037         if not Contents:
   2038             Contents = self.FileIn
   2039         KeyPattern = re.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key, re.S)
   2040         if KeyPattern.search(Contents):
   2041             return True
   2042         return False
   2043     
   2044     def CheckPcdInfo(self, PcdCName):
   2045         PromptKey = 'STR_%s_PROMPT' % PcdCName.replace('.', '_')
   2046         PcdPrompt = self.CheckKeyValid(PromptKey)
   2047         self.PrintLog(PromptKey, PcdPrompt)
   2048         HelpKey = 'STR_%s_HELP' % PcdCName.replace('.', '_')
   2049         PcdHelp = self.CheckKeyValid(HelpKey)
   2050         self.PrintLog(HelpKey, PcdHelp)
   2051     
   2052     def PrintLog(self, Key, Value):
   2053         if not Value and Key not in self.Missing:
   2054             Msg = '%s is missing in the %s file.' % (Key, self.FileName)
   2055             EdkLogger.warn('Parser', Msg)
   2056             EccGlobalData.gDb.TblReport.Insert(EccToolError.ERROR_GENERAL_CHECK_UNI_HELP_INFO, OtherMsg=Msg, BelongsToTable='File', BelongsToItem=-2)
   2057             self.Missing.append(Key)
   2058 
   2059 ##

   2060 #

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

   2062 # script.

   2063 #

   2064 if __name__ == '__main__':
   2065     pass
   2066 
   2067