]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools: Use absolute import in Workspace
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileParser.py
index fabc7ed9862fe8d86a020d5411c2cbf0a86f46a1..fbfc182c8bfff2f142da3a7c7aec80b157fcfdf1 100644 (file)
-## @file
-# This file is used to parse meta files
-#
-# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution.  The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php
-#
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-
-##
-# Import Modules
-#
-import os
-import time
-import copy
-
-import Common.EdkLogger as EdkLogger
-from CommonDataClass.DataClass import *
-from Common.DataType import *
-from Common.String import *
-from Common.Misc import Blist, GuidStructureStringToGuidString, CheckPcdDatum
-
-## Base class of parser
-#
-#  This class is used for derivation purpose. The specific parser for one kind
-# type file must derive this class and implement some public interfaces.
-#
-#   @param      FilePath        The path of platform description file
-#   @param      FileType        The raw data of DSC file
-#   @param      Table           Database used to retrieve module/package information
-#   @param      Macros          Macros used for replacement in file
-#   @param      Owner           Owner ID (for sub-section parsing)
-#   @param      From            ID from which the data comes (for !INCLUDE directive)
-#
-class MetaFileParser(object):
-    # data type (file content) for specific file type
-    DataType = {}
-
-    # Parser objects used to implement singleton
-    MetaFiles = {}
-
-    ## Factory method
-    #
-    # One file, one parser object. This factory method makes sure that there's
-    # only one object constructed for one meta file.
-    #
-    #   @param  Class           class object of real AutoGen class
-    #                           (InfParser, DecParser or DscParser)
-    #   @param  FilePath        The path of meta file
-    #   @param  *args           The specific class related parameters
-    #   @param  **kwargs        The specific class related dict parameters
-    #
-    def __new__(Class, FilePath, *args, **kwargs):
-        if FilePath in Class.MetaFiles:
-            return Class.MetaFiles[FilePath]
-        else:
-            ParserObject = super(MetaFileParser, Class).__new__(Class)
-            Class.MetaFiles[FilePath] = ParserObject
-            return ParserObject
-
-    ## Constructor of MetaFileParser
-    #
-    #  Initialize object of MetaFileParser
-    #
-    #   @param      FilePath        The path of platform description file
-    #   @param      FileType        The raw data of DSC file
-    #   @param      Table           Database used to retrieve module/package information
-    #   @param      Macros          Macros used for replacement in file
-    #   @param      Owner           Owner ID (for sub-section parsing)
-    #   @param      From            ID from which the data comes (for !INCLUDE directive)
-    #
-    def __init__(self, FilePath, FileType, Table, Macros=None, Owner=-1, From=-1):
-        # prevent re-initialization
-        if hasattr(self, "_Table"):
-            return
-        self._Table = Table
-        self._FileType = FileType
-        self.MetaFile = FilePath
-        self._FileDir = os.path.dirname(self.MetaFile)
-        self._Macros = copy.copy(Macros)
-        self._Macros["WORKSPACE"] = os.environ["WORKSPACE"]
-
-        # for recursive parsing
-        self._Owner = Owner
-        self._From = From
-
-        # parsr status for parsing
-        self._Content = None
-        self._ValueList = ['', '', '', '', '']
-        self._Scope = []
-        self._LineIndex = 0
-        self._CurrentLine = ''
-        self._SectionType = MODEL_UNKNOWN
-        self._SectionName = ''
-        self._InSubsection = False
-        self._SubsectionType = MODEL_UNKNOWN
-        self._SubsectionName = ''
-        self._LastItem = -1
-        self._Enabled = 0
-        self._Finished = False
-
-    ## Store the parsed data in table
-    def _Store(self, *Args):
-        return self._Table.Insert(*Args)
-
-    ## Virtual method for starting parse
-    def Start(self):
-        raise NotImplementedError
-
-    ## Set parsing complete flag in both class and table
-    def _Done(self):
-        self._Finished = True
-        ## Do not set end flag when processing included files
-        if self._From == -1:
-            self._Table.SetEndFlag()
-
-    ## Return the table containg parsed data
-    #
-    #   If the parse complete flag is not set, this method will try to parse the
-    # file before return the table
-    #
-    def _GetTable(self):
-        if not self._Finished:
-            self.Start()
-        return self._Table
-
-    ## Get the parse complete flag
-    def _GetFinished(self):
-        return self._Finished
-
-    ## Set the complete flag
-    def _SetFinished(self, Value):
-        self._Finished = Value
-
-    ## Use [] style to query data in table, just for readability
-    #
-    #   DataInfo = [data_type, scope1(arch), scope2(platform,moduletype)]
-    #
-    def __getitem__(self, DataInfo):
-        if type(DataInfo) != type(()):
-            DataInfo = (DataInfo,)
-        return self.Table.Query(*DataInfo)
-
-    ## Data parser for the common format in different type of file
-    #
-    #   The common format in the meatfile is like
-    #
-    #       xxx1 | xxx2 | xxx3
-    #
-    def _CommonParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
-        self._ValueList[0:len(TokenList)] = TokenList
-
-    ## Data parser for the format in which there's path
-    #
-    #   Only path can have macro used. So we need to replace them before use.
-    #
-    def _PathParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
-        self._ValueList[0:len(TokenList)] = TokenList
-        if len(self._Macros) > 0:
-            for Index in range(0, len(self._ValueList)):
-                Value = self._ValueList[Index]
-                if Value == None or Value == '':
-                    continue
-                self._ValueList[Index] = NormPath(Value, self._Macros)
-
-    ## Skip unsupported data
-    def _Skip(self):
-        EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
-                        Line=self._LineIndex+1, ExtraData=self._CurrentLine);
-        self._ValueList[0:1] = [self._CurrentLine]
-
-    ## Section header parser
-    #
-    #   The section header is always in following format:
-    #
-    #       [section_name.arch<.platform|module_type>]
-    #
-    def _SectionHeaderParser(self):
-        self._Scope = []
-        self._SectionName = ''
-        ArchList = set()
-        for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
-            if Item == '':
-                continue
-            ItemList = GetSplitValueList(Item, TAB_SPLIT)
-            # different section should not mix in one section
-            if self._SectionName != '' and self._SectionName != ItemList[0].upper():
-                EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
-                                File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
-            self._SectionName = ItemList[0].upper()
-            if self._SectionName in self.DataType:
-                self._SectionType = self.DataType[self._SectionName]
-            else:
-                self._SectionType = MODEL_UNKNOWN
-                EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
-                                Line=self._LineIndex+1, ExtraData=self._CurrentLine)
-            # S1 is always Arch
-            if len(ItemList) > 1:
-                S1 = ItemList[1].upper()
-            else:
-                S1 = 'COMMON'
-            ArchList.add(S1)
-            # S2 may be Platform or ModuleType
-            if len(ItemList) > 2:
-                S2 = ItemList[2].upper()
-            else:
-                S2 = 'COMMON'
-            self._Scope.append([S1, S2])
-
-        # 'COMMON' must not be used with specific ARCHs at the same section
-        if 'COMMON' in ArchList and len(ArchList) > 1:
-            EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
-                            File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
-
-    ## [defines] section parser
-    def _DefineParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
-        self._ValueList[0:len(TokenList)] = TokenList
-        if self._ValueList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-
-    ## DEFINE name=value parser
-    def _MacroParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
-        MacroType = TokenList[0]
-        if len(TokenList) < 2 or TokenList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No macro name/value given",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        TokenList = GetSplitValueList(TokenList[1], TAB_EQUAL_SPLIT, 1)
-        if TokenList[0] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-
-        # Macros defined in the command line override ones defined in the meta-data file
-        if not TokenList[0] in self._Macros:
-            if len(TokenList) == 1:
-                self._Macros[TokenList[0]] = ''
-            else:
-                # keep the macro definition for later use
-                self._Macros[TokenList[0]] = ReplaceMacro(TokenList[1], self._Macros, False)
-
-        return TokenList[0], self._Macros[TokenList[0]]
-
-    ## [BuildOptions] section parser
-    def _BuildOptionParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
-        TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
-        if len(TokenList2) == 2:
-            self._ValueList[0] = TokenList2[0]  # toolchain family
-            self._ValueList[1] = TokenList2[1]  # keys
-        else:
-            self._ValueList[1] = TokenList[0]
-        if len(TokenList) == 2:                 # value
-            self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
-
-        if self._ValueList[1].count('_') != 4:
-            EdkLogger.error(
-                'Parser',
-                FORMAT_INVALID,
-                "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
-                ExtraData=self._CurrentLine,
-                File=self.MetaFile,
-                Line=self._LineIndex+1
-                )
-
-    _SectionParser  = {}
-    Table           = property(_GetTable)
-    Finished        = property(_GetFinished, _SetFinished)
-
-
-## INF file parser class
-#
-#   @param      FilePath        The path of platform description file
-#   @param      FileType        The raw data of DSC file
-#   @param      Table           Database used to retrieve module/package information
-#   @param      Macros          Macros used for replacement in file
-#
-class InfParser(MetaFileParser):
-    # INF file supported data types (one type per section)
-    DataType = {
-        TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
-        TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
-        TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
-        TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
-        TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
-        TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
-        TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
-        TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
-        TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
-        TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
-        TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
-        TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
-        TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
-        TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
-        TAB_GUIDS.upper() : MODEL_EFI_GUID,
-        TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
-        TAB_PPIS.upper() : MODEL_EFI_PPI,
-        TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
-        TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
-        TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
-    }
-
-    ## Constructor of InfParser
-    #
-    #  Initialize object of InfParser
-    #
-    #   @param      FilePath        The path of module description file
-    #   @param      FileType        The raw data of DSC file
-    #   @param      Table           Database used to retrieve module/package information
-    #   @param      Macros          Macros used for replacement in file
-    #
-    def __init__(self, FilePath, FileType, Table, Macros=None):
-        MetaFileParser.__init__(self, FilePath, FileType, Table, Macros)
-
-    ## Parser starter
-    def Start(self):
-        NmakeLine = ''
-        try:
-            self._Content = open(self.MetaFile, 'r').readlines()
-        except:
-            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
-
-        # parse the file line by line
-        IsFindBlockComment = False
-
-        for Index in range(0, len(self._Content)):
-            # skip empty, commented, block commented lines
-            Line = CleanString(self._Content[Index], AllowCppStyleComment=True)
-            NextLine = ''
-            if Index + 1 < len(self._Content):
-                NextLine = CleanString(self._Content[Index + 1])
-            if Line == '':
-                continue
-            if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:
-                IsFindBlockComment = True
-                continue
-            if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:
-                IsFindBlockComment = False
-                continue
-            if IsFindBlockComment:
-                continue
-
-            self._LineIndex = Index
-            self._CurrentLine = Line
-
-            # section header
-            if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
-                self._SectionHeaderParser()
-                continue
-            # merge two lines specified by '\' in section NMAKE
-            elif self._SectionType == MODEL_META_DATA_NMAKE:
-                if Line[-1] == '\\':
-                    if NextLine == '':
-                        self._CurrentLine = NmakeLine + Line[0:-1]
-                        NmakeLine = ''
-                    else:
-                        if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
-                            self._CurrentLine = NmakeLine + Line[0:-1]
-                            NmakeLine = ''
-                        else:
-                            NmakeLine = NmakeLine + ' ' + Line[0:-1]
-                            continue
-                else:
-                    self._CurrentLine = NmakeLine + Line
-                    NmakeLine = ''
-            elif Line.upper().startswith('DEFINE '):
-                # file private macros
-                self._MacroParser()
-                continue
-
-            # section content
-            self._ValueList = ['','','']
-            # parse current line, result will be put in self._ValueList
-            self._SectionParser[self._SectionType](self)
-            if self._ValueList == None:
-                continue
-            #
-            # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
-            # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
-            #
-            for Arch, Platform in self._Scope:
-                self._Store(self._SectionType,
-                            self._ValueList[0],
-                            self._ValueList[1],
-                            self._ValueList[2],
-                            Arch,
-                            Platform,
-                            self._Owner,
-                            self._LineIndex+1,
-                            -1,
-                            self._LineIndex+1,
-                            -1,
-                            0
-                            )
-        if IsFindBlockComment:
-            EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */", 
-                            File=self.MetaFile)
-        self._Done()
-
-    ## Data parser for the format in which there's path
-    #
-    #   Only path can have macro used. So we need to replace them before use.
-    #
-    def _IncludeParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
-        self._ValueList[0:len(TokenList)] = TokenList
-        if len(self._Macros) > 0:
-            for Index in range(0, len(self._ValueList)):
-                Value = self._ValueList[Index]
-                if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
-                    Value = '$(EDK_SOURCE)' + Value[17:]
-                if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:
-                    pass
-                elif Value.startswith('.'):
-                    pass
-                elif Value.startswith('$('):
-                    pass
-                else:
-                    Value = '$(EFI_SOURCE)/' + Value
-
-                if Value == None or Value == '':
-                    continue
-                self._ValueList[Index] = NormPath(Value, self._Macros)
-
-    ## Parse [Sources] section
-    #
-    #   Only path can have macro used. So we need to replace them before use.
-    #
-    def _SourceFileParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
-        self._ValueList[0:len(TokenList)] = TokenList
-        # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
-        if 'COMPONENT_TYPE' in self._Macros:
-            if self._Macros['COMPONENT_TYPE'].upper() == 'ACPITABLE':
-                self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
-        if self._Macros['BASE_NAME'] == 'Microcode':
-            pass
-        if len(self._Macros) > 0:
-            for Index in range(0, len(self._ValueList)):
-                Value = self._ValueList[Index]
-                if Value == None or Value == '':
-                    continue
-                self._ValueList[Index] = NormPath(Value, self._Macros)
-
-    ## Parse [Binaries] section
-    #
-    #   Only path can have macro used. So we need to replace them before use.
-    #
-    def _BinaryFileParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
-        if len(TokenList) < 2:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
-                            ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if not TokenList[0]:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
-                            ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if not TokenList[1]:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
-                            ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        self._ValueList[0:len(TokenList)] = TokenList
-        self._ValueList[1] = NormPath(self._ValueList[1], self._Macros)
-
-    ## [defines] section parser
-    def _DefineParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
-        self._ValueList[0:len(TokenList)] = TokenList
-        if self._ValueList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        self._Macros[TokenList[0]] = ReplaceMacro(TokenList[1], self._Macros, False)
-        
-    ## [nmake] section parser (EDK.x style only)
-    def _NmakeParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
-        self._ValueList[0:len(TokenList)] = TokenList
-        # remove macros
-        self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, False)
-        # remove self-reference in macro setting
-        #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
-
-    ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
-    def _PcdParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
-        ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
-        if len(ValueList) != 2:
-            EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
-                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        self._ValueList[0:1] = ValueList
-        if len(TokenList) > 1:
-            self._ValueList[2] = TokenList[1]
-        if self._ValueList[0] == '' or self._ValueList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
-                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
-        if self._ValueList[2] != '':
-            InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
-            if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
-                self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
-            elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
-                self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
-
-    ## [depex] section parser
-    def _DepexParser(self):
-        self._ValueList[0:1] = [self._CurrentLine]
-
-    _SectionParser = {
-        MODEL_UNKNOWN                   :   MetaFileParser._Skip,
-        MODEL_META_DATA_HEADER          :   _DefineParser,
-        MODEL_META_DATA_BUILD_OPTION    :   MetaFileParser._BuildOptionParser,
-        MODEL_EFI_INCLUDE               :   _IncludeParser,                 # for EDK.x modules
-        MODEL_EFI_LIBRARY_INSTANCE      :   MetaFileParser._CommonParser,   # for EDK.x modules
-        MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,
-        MODEL_META_DATA_PACKAGE         :   MetaFileParser._PathParser,
-        MODEL_META_DATA_NMAKE           :   _NmakeParser,                   # for EDK.x modules
-        MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,
-        MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,
-        MODEL_PCD_FEATURE_FLAG          :   _PcdParser,
-        MODEL_PCD_DYNAMIC_EX            :   _PcdParser,
-        MODEL_PCD_DYNAMIC               :   _PcdParser,
-        MODEL_EFI_SOURCE_FILE           :   _SourceFileParser,
-        MODEL_EFI_GUID                  :   MetaFileParser._CommonParser,
-        MODEL_EFI_PROTOCOL              :   MetaFileParser._CommonParser,
-        MODEL_EFI_PPI                   :   MetaFileParser._CommonParser,
-        MODEL_EFI_DEPEX                 :   _DepexParser,
-        MODEL_EFI_BINARY_FILE           :   _BinaryFileParser,
-        MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._Skip,
-    }
-
-## DSC file parser class
-#
-#   @param      FilePath        The path of platform description file
-#   @param      FileType        The raw data of DSC file
-#   @param      Table           Database used to retrieve module/package information
-#   @param      Macros          Macros used for replacement in file
-#   @param      Owner           Owner ID (for sub-section parsing)
-#   @param      From            ID from which the data comes (for !INCLUDE directive)
-#
-class DscParser(MetaFileParser):
-    # DSC file supported data types (one type per section)
-    DataType = {
-        TAB_SKUIDS.upper()                          :   MODEL_EFI_SKU_ID,
-        TAB_LIBRARIES.upper()                       :   MODEL_EFI_LIBRARY_INSTANCE,
-        TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,
-        TAB_BUILD_OPTIONS.upper()                   :   MODEL_META_DATA_BUILD_OPTION,
-        TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,
-        TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,
-        TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,
-        TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper()       :   MODEL_PCD_DYNAMIC_DEFAULT,
-        TAB_PCDS_DYNAMIC_HII_NULL.upper()           :   MODEL_PCD_DYNAMIC_HII,
-        TAB_PCDS_DYNAMIC_VPD_NULL.upper()           :   MODEL_PCD_DYNAMIC_VPD,
-        TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper()    :   MODEL_PCD_DYNAMIC_EX_DEFAULT,
-        TAB_PCDS_DYNAMIC_EX_HII_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_HII,
-        TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_VPD,
-        TAB_COMPONENTS.upper()                      :   MODEL_META_DATA_COMPONENT,
-        TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() :   MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
-        TAB_DSC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,
-        TAB_INCLUDE.upper()                         :   MODEL_META_DATA_INCLUDE,
-        TAB_IF.upper()                              :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
-        TAB_IF_DEF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
-        TAB_IF_N_DEF.upper()                        :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
-        TAB_ELSE_IF.upper()                         :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
-        TAB_ELSE.upper()                            :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
-        TAB_END_IF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
-    }
-
-    # sections which allow "!include" directive
-    _IncludeAllowedSection = [
-        TAB_COMMON_DEFINES.upper(),
-        TAB_LIBRARIES.upper(),
-        TAB_LIBRARY_CLASSES.upper(),
-        TAB_SKUIDS.upper(),
-        TAB_COMPONENTS.upper(),
-        TAB_BUILD_OPTIONS.upper(),
-        TAB_PCDS_FIXED_AT_BUILD_NULL.upper(),
-        TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper(),
-        TAB_PCDS_FEATURE_FLAG_NULL.upper(),
-        TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper(),
-        TAB_PCDS_DYNAMIC_HII_NULL.upper(),
-        TAB_PCDS_DYNAMIC_VPD_NULL.upper(),
-        TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper(),
-        TAB_PCDS_DYNAMIC_EX_HII_NULL.upper(),
-        TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper(),
-        ]
-
-    # operators which can be used in "!if/!ifdef/!ifndef" directives
-    _OP_ = {
-        "!"     :   lambda a:   not a,
-        "!="    :   lambda a,b: a!=b,
-        "=="    :   lambda a,b: a==b,
-        ">"     :   lambda a,b: a>b,
-        "<"     :   lambda a,b: a<b,
-        "=>"    :   lambda a,b: a>=b,
-        ">="    :   lambda a,b: a>=b,
-        "<="    :   lambda a,b: a<=b,
-        "=<"    :   lambda a,b: a<=b,
-    }
-
-    ## Constructor of DscParser
-    #
-    #  Initialize object of DscParser
-    #
-    #   @param      FilePath        The path of platform description file
-    #   @param      FileType        The raw data of DSC file
-    #   @param      Table           Database used to retrieve module/package information
-    #   @param      Macros          Macros used for replacement in file
-    #   @param      Owner           Owner ID (for sub-section parsing)
-    #   @param      From            ID from which the data comes (for !INCLUDE directive)
-    #
-    def __init__(self, FilePath, FileType, Table, Macros=None, Owner=-1, From=-1):
-        MetaFileParser.__init__(self, FilePath, FileType, Table, Macros, Owner, From)
-        # to store conditional directive evaluation result
-        self._Eval = Blist()
-
-    ## Parser starter
-    def Start(self):
-        try:
-            if self._Content == None:
-                self._Content = open(self.MetaFile, 'r').readlines()
-        except:
-            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
-
-        for Index in range(0, len(self._Content)):
-            Line = CleanString(self._Content[Index])
-            # skip empty line
-            if Line == '':
-                continue
-            self._CurrentLine = Line
-            self._LineIndex = Index
-            if self._InSubsection and self._Owner == -1:
-                self._Owner = self._LastItem
-            
-            # section header
-            if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
-                self._SectionHeaderParser()
-                continue
-            # subsection ending
-            elif Line[0] == '}':
-                self._InSubsection = False
-                self._SubsectionType = MODEL_UNKNOWN
-                self._SubsectionName = ''
-                self._Owner = -1
-                continue
-            # subsection header
-            elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
-                self._SubsectionHeaderParser()
-                continue
-            # directive line
-            elif Line[0] == '!':
-                self._DirectiveParser()
-                continue
-            # file private macros
-            elif Line.upper().startswith('DEFINE '):
-                if self._Enabled < 0:
-                    # Do not parse the macro and add it to self._Macros dictionary if directives
-                    # statement is evaluated to false.
-                    continue
-                
-                (Name, Value) = self._MacroParser()
-                # Make the defined macro in DSC [Defines] section also
-                # available for FDF file.
-                if self._SectionName == TAB_COMMON_DEFINES.upper():
-                    self._LastItem = self._Store(
-                    MODEL_META_DATA_GLOBAL_DEFINE,
-                    Name,
-                    Value,
-                    '',
-                    'COMMON',
-                    'COMMON',
-                    self._Owner,
-                    self._From,
-                    self._LineIndex+1,
-                    -1,
-                    self._LineIndex+1,
-                    -1,
-                    self._Enabled
-                    )
-                continue
-            elif Line.upper().startswith('EDK_GLOBAL '):
-                if self._Enabled < 0:
-                    # Do not parse the macro and add it to self._Macros dictionary
-                    # if previous directives statement is evaluated to false.
-                    continue
-                
-                (Name, Value) = self._MacroParser()
-                for Arch, ModuleType in self._Scope:
-                    self._LastItem = self._Store(
-                    MODEL_META_DATA_DEFINE,
-                    Name,
-                    Value,
-                    '',
-                    Arch,
-                    'COMMON',
-                    self._Owner,
-                    self._From,
-                    self._LineIndex+1,
-                    -1,
-                    self._LineIndex+1,
-                    -1,
-                    self._Enabled
-                    )
-                continue
-
-            # section content
-            if self._InSubsection:
-                SectionType = self._SubsectionType
-                SectionName = self._SubsectionName
-            else:
-                SectionType = self._SectionType
-                SectionName = self._SectionName
-
-            self._ValueList = ['', '', '']
-            self._SectionParser[SectionType](self)
-            if self._ValueList == None:
-                continue
-
-            #
-            # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
-            # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
-            #
-            for Arch, ModuleType in self._Scope:
-                self._LastItem = self._Store(
-                    SectionType,
-                    self._ValueList[0],
-                    self._ValueList[1],
-                    self._ValueList[2],
-                    Arch,
-                    ModuleType,
-                    self._Owner,
-                    self._From,
-                    self._LineIndex+1,
-                    -1,
-                    self._LineIndex+1,
-                    -1,
-                    self._Enabled
-                    )
-        self._Done()
-
-    ## [defines] section parser
-    def _DefineParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
-        if len(TokenList) < 2:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        # 'FLASH_DEFINITION', 'OUTPUT_DIRECTORY' need special processing
-        if TokenList[0] in ['FLASH_DEFINITION', 'OUTPUT_DIRECTORY']:
-            TokenList[1] = NormPath(TokenList[1], self._Macros)
-        self._ValueList[0:len(TokenList)] = TokenList
-        # Treat elements in the [defines] section as global macros for FDF file.
-        self._LastItem = self._Store(
-                            MODEL_META_DATA_GLOBAL_DEFINE,
-                            TokenList[0],
-                            TokenList[1],
-                            '',
-                            'COMMON',
-                            'COMMON',
-                            self._Owner,
-                            self._From,
-                            self._LineIndex+1,
-                            -1,
-                            self._LineIndex+1,
-                            -1,
-                            self._Enabled
-                            )
-
-    ## <subsection_header> parser
-    def _SubsectionHeaderParser(self):
-        self._SubsectionName = self._CurrentLine[1:-1].upper()
-        if self._SubsectionName in self.DataType:
-            self._SubsectionType = self.DataType[self._SubsectionName]
-        else:
-            self._SubsectionType = MODEL_UNKNOWN
-            EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
-                            Line=self._LineIndex+1, ExtraData=self._CurrentLine)
-
-    ## Directive statement parser
-    def _DirectiveParser(self):
-        self._ValueList = ['','','']
-        TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
-        self._ValueList[0:len(TokenList)] = TokenList
-        DirectiveName = self._ValueList[0].upper()
-        if DirectiveName not in self.DataType:
-            EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
-            EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
-                            File=self.MetaFile, Line=self._LineIndex+1,
-                            ExtraData=self._CurrentLine)
-        # keep the directive in database first
-        self._LastItem = self._Store(
-            self.DataType[DirectiveName],
-            self._ValueList[0],
-            self._ValueList[1],
-            self._ValueList[2],
-            'COMMON',
-            'COMMON',
-            self._Owner,
-            self._From,
-            self._LineIndex + 1,
-            -1,
-            self._LineIndex + 1,
-            -1,
-            0
-            )
-
-        # process the directive
-        if DirectiveName == "!INCLUDE":
-            if not self._SectionName in self._IncludeAllowedSection:
-                EdkLogger.error("Parser", FORMAT_INVALID, File=self.MetaFile, Line=self._LineIndex+1,
-                                ExtraData="'!include' is not allowed under section [%s]" % self._SectionName)
-            # the included file must be relative to workspace
-            IncludedFile = os.path.join(os.environ["WORKSPACE"], NormPath(self._ValueList[1], self._Macros))
-            Parser = DscParser(IncludedFile, self._FileType, self._Table, self._Macros, From=self._LastItem)
-            # set the parser status with current status
-            Parser._SectionName = self._SectionName
-            Parser._SectionType = self._SectionType
-            Parser._Scope = self._Scope
-            Parser._Enabled = self._Enabled
-            try:
-                Parser.Start()
-            except:
-                EdkLogger.error("Parser", PARSER_ERROR, File=self.MetaFile, Line=self._LineIndex+1,
-                                ExtraData="Failed to parse content in file %s" % IncludedFile)
-            # insert an imaginary token in the DSC table to indicate its external dependency on another file
-            self._Store(MODEL_EXTERNAL_DEPENDENCY, IncludedFile, str(os.stat(IncludedFile)[8]), "")
-            # update current status with sub-parser's status
-            self._SectionName = Parser._SectionName
-            self._SectionType = Parser._SectionType
-            self._Scope       = Parser._Scope
-            self._Enabled     = Parser._Enabled
-            self._Macros.update(Parser._Macros)
-        else:
-            if DirectiveName in ["!IF", "!IFDEF", "!IFNDEF"]:
-                # evaluate the expression
-                Result = self._Evaluate(self._ValueList[1])
-                if DirectiveName == "!IFNDEF":
-                    Result = not Result
-                self._Eval.append(Result)
-            elif DirectiveName in ["!ELSEIF"]:
-                # evaluate the expression
-                self._Eval[-1] = (not self._Eval[-1]) & self._Evaluate(self._ValueList[1])
-            elif DirectiveName in ["!ELSE"]:
-                self._Eval[-1] = not self._Eval[-1]
-            elif DirectiveName in ["!ENDIF"]:
-                if len(self._Eval) > 0:
-                    self._Eval.pop()
-                else:
-                    EdkLogger.error("Parser", FORMAT_INVALID, "!IF..[!ELSE]..!ENDIF doesn't match",
-                                    File=self.MetaFile, Line=self._LineIndex+1)
-            if self._Eval.Result == False:
-                self._Enabled = 0 - len(self._Eval)
-            else:
-                self._Enabled = len(self._Eval)
-
-    ## Evaluate the Token for its value; for now only macros are supported.
-    def _EvaluateToken(self, TokenName, Expression):
-        if TokenName.startswith("$(") and TokenName.endswith(")"):
-            Name = TokenName[2:-1]
-            return self._Macros.get(Name)
-        else:
-            EdkLogger.error('Parser', FORMAT_INVALID, "Unknown operand '%(Token)s', "
-                            "please use '$(%(Token)s)' if '%(Token)s' is a macro" % {"Token" : TokenName},
-                            File=self.MetaFile, Line=self._LineIndex+1, ExtraData=Expression)
-    
-    ## Evaluate the value of expression in "if/ifdef/ifndef" directives
-    def _Evaluate(self, Expression):
-        TokenList = Expression.split()
-        TokenNumber = len(TokenList)
-        # one operand, guess it's just a macro name
-        if TokenNumber == 1:
-            TokenValue =  self._EvaluateToken(TokenList[0], Expression)
-            return TokenValue != None
-        # two operands, suppose it's "!xxx" format
-        elif TokenNumber == 2:
-            Op = TokenList[0]
-            if Op not in self._OP_:
-                EdkLogger.error('Parser', FORMAT_INVALID, "Unsupported operator [%s]" % Op, File=self.MetaFile,
-                                Line=self._LineIndex+1, ExtraData=Expression)
-            if TokenList[1].upper() == 'TRUE':
-                Value = True
-            else:
-                Value = False
-            return self._OP_[Op](Value)
-        # three operands
-        elif TokenNumber == 3:
-            TokenValue = TokenList[0] 
-            if TokenValue[0] in ["'", '"'] and TokenValue[-1] in ["'", '"']:
-                TokenValue = TokenValue[1:-1]             
-            if TokenValue.startswith("$(") and TokenValue.endswith(")"):
-                TokenValue = self._EvaluateToken(TokenValue, Expression)
-            if TokenValue[0] in ["'", '"'] and TokenValue[-1] in ["'", '"']:
-                TokenValue = TokenValue[1:-1]                
-            if TokenValue == None:
-                return False
-            Value = TokenList[2]
-            if Value[0] in ["'", '"'] and Value[-1] in ["'", '"']:
-                Value = Value[1:-1]            
-            if Value.startswith("$(") and Value.endswith(")"):
-                Value = self._EvaluateToken(Value, Expression)          
-            if Value[0] in ["'", '"'] and Value[-1] in ["'", '"']:
-                Value = Value[1:-1]
-            Op = TokenList[1]
-            if Op not in self._OP_:
-                EdkLogger.error('Parser', FORMAT_INVALID, "Unsupported operator [%s]" % Op, File=self.MetaFile,
-                                Line=self._LineIndex+1, ExtraData=Expression)
-            return self._OP_[Op](TokenValue, Value)
-        else:
-            EdkLogger.error('Parser', FORMAT_INVALID, File=self.MetaFile, Line=self._LineIndex+1,
-                            ExtraData=Expression)
-
-    ## PCD sections parser
-    #
-    #   [PcdsFixedAtBuild]
-    #   [PcdsPatchableInModule]
-    #   [PcdsFeatureFlag]
-    #   [PcdsDynamicEx
-    #   [PcdsDynamicExDefault]
-    #   [PcdsDynamicExVpd]
-    #   [PcdsDynamicExHii]
-    #   [PcdsDynamic]
-    #   [PcdsDynamicDefault]
-    #   [PcdsDynamicVpd]
-    #   [PcdsDynamicHii]
-    #
-    def _PcdParser(self):
-        TokenList = GetSplitValueList(ReplaceMacro(self._CurrentLine, self._Macros), TAB_VALUE_SPLIT, 1)
-        self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
-        if len(TokenList) == 2:
-            self._ValueList[2] = TokenList[1]
-        if self._ValueList[0] == '' or self._ValueList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
-                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if self._ValueList[2] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
-                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
-        DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
-        if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
-            self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
-        elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
-            self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
-            
-    ## [components] section parser
-    def _ComponentParser(self):
-        if self._CurrentLine[-1] == '{':
-            self._ValueList[0] = self._CurrentLine[0:-1].strip()
-            self._InSubsection = True
-        else:
-            self._ValueList[0] = self._CurrentLine
-        if len(self._Macros) > 0:
-            self._ValueList[0] = NormPath(self._ValueList[0], self._Macros)
-
-    def _LibraryClassParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
-        if len(TokenList) < 2:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
-                            ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if TokenList[0] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
-                            ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if TokenList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
-                            ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        self._ValueList[0:len(TokenList)] = TokenList
-        if len(self._Macros) > 0:
-            self._ValueList[1] = NormPath(self._ValueList[1], self._Macros)
-
-    def _CompponentSourceOverridePathParser(self):
-        if len(self._Macros) > 0:
-            self._ValueList[0] = NormPath(self._CurrentLine, self._Macros)
-
-    _SectionParser = {
-        MODEL_META_DATA_HEADER                         :   _DefineParser,
-        MODEL_EFI_SKU_ID                               :   MetaFileParser._CommonParser,
-        MODEL_EFI_LIBRARY_INSTANCE                     :   MetaFileParser._PathParser,
-        MODEL_EFI_LIBRARY_CLASS                        :   _LibraryClassParser,
-        MODEL_PCD_FIXED_AT_BUILD                       :   _PcdParser,
-        MODEL_PCD_PATCHABLE_IN_MODULE                  :   _PcdParser,
-        MODEL_PCD_FEATURE_FLAG                         :   _PcdParser,
-        MODEL_PCD_DYNAMIC_DEFAULT                      :   _PcdParser,
-        MODEL_PCD_DYNAMIC_HII                          :   _PcdParser,
-        MODEL_PCD_DYNAMIC_VPD                          :   _PcdParser,
-        MODEL_PCD_DYNAMIC_EX_DEFAULT                   :   _PcdParser,
-        MODEL_PCD_DYNAMIC_EX_HII                       :   _PcdParser,
-        MODEL_PCD_DYNAMIC_EX_VPD                       :   _PcdParser,
-        MODEL_META_DATA_COMPONENT                      :   _ComponentParser,
-        MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH :   _CompponentSourceOverridePathParser,
-        MODEL_META_DATA_BUILD_OPTION                   :   MetaFileParser._BuildOptionParser,
-        MODEL_UNKNOWN                                  :   MetaFileParser._Skip,
-        MODEL_META_DATA_USER_EXTENSION                 :   MetaFileParser._Skip,
-    }
-
-## DEC file parser class
-#
-#   @param      FilePath        The path of platform description file
-#   @param      FileType        The raw data of DSC file
-#   @param      Table           Database used to retrieve module/package information
-#   @param      Macros          Macros used for replacement in file
-#
-class DecParser(MetaFileParser):
-    # DEC file supported data types (one type per section)
-    DataType = {
-        TAB_DEC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,
-        TAB_INCLUDES.upper()                        :   MODEL_EFI_INCLUDE,
-        TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,
-        TAB_GUIDS.upper()                           :   MODEL_EFI_GUID,
-        TAB_PPIS.upper()                            :   MODEL_EFI_PPI,
-        TAB_PROTOCOLS.upper()                       :   MODEL_EFI_PROTOCOL,
-        TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,
-        TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,
-        TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,
-        TAB_PCDS_DYNAMIC_NULL.upper()               :   MODEL_PCD_DYNAMIC,
-        TAB_PCDS_DYNAMIC_EX_NULL.upper()            :   MODEL_PCD_DYNAMIC_EX,
-    }
-
-    ## Constructor of DecParser
-    #
-    #  Initialize object of DecParser
-    #
-    #   @param      FilePath        The path of platform description file
-    #   @param      FileType        The raw data of DSC file
-    #   @param      Table           Database used to retrieve module/package information
-    #   @param      Macros          Macros used for replacement in file
-    #
-    def __init__(self, FilePath, FileType, Table, Macro=None):
-        MetaFileParser.__init__(self, FilePath, FileType, Table, Macro, -1)
-        self._Comments = []
-
-    ## Parser starter
-    def Start(self):
-        try:
-            if self._Content == None:
-                self._Content = open(self.MetaFile, 'r').readlines()
-        except:
-            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
-
-        for Index in range(0, len(self._Content)):
-            Line, Comment = CleanString2(self._Content[Index])
-            self._CurrentLine = Line
-            self._LineIndex = Index
-
-            # save comment for later use
-            if Comment:
-                self._Comments.append((Comment, self._LineIndex+1))
-            # skip empty line
-            if Line == '':
-                continue
-
-            # section header
-            if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
-                self._SectionHeaderParser()
-                self._Comments = []
-                continue
-            elif Line.startswith('DEFINE '):
-                self._MacroParser()
-                continue
-            elif len(self._SectionType) == 0:
-                self._Comments = []
-                continue
-
-            # section content
-            self._ValueList = ['','','']
-            self._SectionParser[self._SectionType[0]](self)
-            if self._ValueList == None:
-                self._Comments = []
-                continue
-
-            #
-            # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
-            # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
-            #
-            for Arch, ModuleType, Type in self._Scope:
-                self._LastItem = self._Store(
-                    Type,
-                    self._ValueList[0],
-                    self._ValueList[1],
-                    self._ValueList[2],
-                    Arch,
-                    ModuleType,
-                    self._Owner,
-                    self._LineIndex+1,
-                    -1,
-                    self._LineIndex+1,
-                    -1,
-                    0
-                    )
-                for Comment, LineNo in self._Comments:
-                    self._Store(
-                        MODEL_META_DATA_COMMENT,
-                        Comment,
-                        self._ValueList[0],
-                        self._ValueList[1],
-                        Arch,
-                        ModuleType,
-                        self._LastItem,
-                        LineNo,
-                        -1,
-                        LineNo,
-                        -1,
-                        0
-                        )
-            self._Comments = []
-        self._Done()
-
-    ## Section header parser
-    #
-    #   The section header is always in following format:
-    #
-    #       [section_name.arch<.platform|module_type>]
-    #
-    def _SectionHeaderParser(self):
-        self._Scope = []
-        self._SectionName = ''
-        self._SectionType = []
-        ArchList = set()
-        for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
-            if Item == '':
-                continue
-            ItemList = GetSplitValueList(Item, TAB_SPLIT)
-
-            # different types of PCD are permissible in one section
-            self._SectionName = ItemList[0].upper()
-            if self._SectionName in self.DataType:
-                if self.DataType[self._SectionName] not in self._SectionType:
-                    self._SectionType.append(self.DataType[self._SectionName])
-            else:
-                EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
-                                Line=self._LineIndex+1, ExtraData=self._CurrentLine)
-                continue
-
-            if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
-                EdkLogger.error(
-                            'Parser',
-                            FORMAT_INVALID,
-                            "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
-                            File=self.MetaFile,
-                            Line=self._LineIndex+1,
-                            ExtraData=self._CurrentLine
-                            )
-            # S1 is always Arch
-            if len(ItemList) > 1:
-                S1 = ItemList[1].upper()
-            else:
-                S1 = 'COMMON'
-            ArchList.add(S1)
-            # S2 may be Platform or ModuleType
-            if len(ItemList) > 2:
-                S2 = ItemList[2].upper()
-            else:
-                S2 = 'COMMON'
-            if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
-                self._Scope.append([S1, S2, self.DataType[self._SectionName]])
-
-        # 'COMMON' must not be used with specific ARCHs at the same section
-        if 'COMMON' in ArchList and len(ArchList) > 1:
-            EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
-                            File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
-
-    ## [guids], [ppis] and [protocols] section parser
-    def _GuidParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
-        if len(TokenList) < 2:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
-                            ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if TokenList[0] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
-                            ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if TokenList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
-                            ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
-                            ExtraData=self._CurrentLine + \
-                                      " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        self._ValueList[0] = TokenList[0]
-        self._ValueList[1] = TokenList[1]
-
-    ## PCD sections parser
-    #
-    #   [PcdsFixedAtBuild]
-    #   [PcdsPatchableInModule]
-    #   [PcdsFeatureFlag]
-    #   [PcdsDynamicEx
-    #   [PcdsDynamic]
-    #
-    def _PcdParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
-        self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
-        # check PCD information
-        if self._ValueList[0] == '' or self._ValueList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
-                            ExtraData=self._CurrentLine + \
-                                      " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        # check PCD datum information
-        if len(TokenList) < 2 or TokenList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
-                            ExtraData=self._CurrentLine + \
-                                      " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-
-        
-        ValueRe  = re.compile(r'^\s*L?\".*\|.*\"')
-        PtrValue = ValueRe.findall(TokenList[1])
-        
-        # Has VOID* type string, may contain "|" character in the string. 
-        if len(PtrValue) != 0:
-            ptrValueList = re.sub(ValueRe, '', TokenList[1])
-            ValueList    = GetSplitValueList(ptrValueList)
-            ValueList[0] = PtrValue[0]
-        else:
-            ValueList = GetSplitValueList(TokenList[1])
-            
-        
-        # check if there's enough datum information given
-        if len(ValueList) != 3:
-            EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
-                            ExtraData=self._CurrentLine + \
-                                      " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        # check default value
-        if ValueList[0] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
-                            ExtraData=self._CurrentLine + \
-                                      " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        # check datum type
-        if ValueList[1] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
-                            ExtraData=self._CurrentLine + \
-                                      " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        # check token of the PCD
-        if ValueList[2] == '':
-            EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
-                            ExtraData=self._CurrentLine + \
-                                      " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        # check format of default value against the datum type
-        IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
-        if not IsValid:
-            EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
-                            File=self.MetaFile, Line=self._LineIndex+1)
-        if ValueList[0] in ['True', 'true', 'TRUE']:
-            ValueList[0] = '1'
-        elif ValueList[0] in ['False', 'false', 'FALSE']:
-            ValueList[0] = '0'
-
-        self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
-
-    _SectionParser = {
-        MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,
-        MODEL_EFI_INCLUDE               :   MetaFileParser._PathParser,
-        MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,
-        MODEL_EFI_GUID                  :   _GuidParser,
-        MODEL_EFI_PPI                   :   _GuidParser,
-        MODEL_EFI_PROTOCOL              :   _GuidParser,
-        MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,
-        MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,
-        MODEL_PCD_FEATURE_FLAG          :   _PcdParser,
-        MODEL_PCD_DYNAMIC               :   _PcdParser,
-        MODEL_PCD_DYNAMIC_EX            :   _PcdParser,
-        MODEL_UNKNOWN                   :   MetaFileParser._Skip,
-        MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._Skip,
-    }
-
-##
-#
-# This acts like the main() function for the script, unless it is 'import'ed into another
-# script.
-#
-if __name__ == '__main__':
-    pass
-
+## @file\r
+# This file is used to parse meta files\r
+#\r
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+##\r
+# Import Modules\r
+#\r
+from __future__ import print_function\r
+from __future__ import absolute_import\r
+import Common.LongFilePathOs as os\r
+import re\r
+import time\r
+import copy\r
+import md5\r
+\r
+import Common.EdkLogger as EdkLogger\r
+import Common.GlobalData as GlobalData\r
+\r
+from CommonDataClass.DataClass import *\r
+from Common.DataType import *\r
+from Common.StringUtils import *\r
+from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue\r
+from Common.Expression import *\r
+from CommonDataClass.Exceptions import *\r
+from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from collections import defaultdict\r
+from .MetaFileTable import MetaFileStorage\r
+from .MetaFileCommentParser import CheckInfComment\r
+\r
+## RegEx for finding file versions\r
+hexVersionPattern = re.compile(r'0[xX][\da-f-A-F]{5,8}')\r
+decVersionPattern = re.compile(r'\d+\.\d+')\r
+\r
+## A decorator used to parse macro definition\r
+def ParseMacro(Parser):\r
+    def MacroParser(self):\r
+        Match = gMacroDefPattern.match(self._CurrentLine)\r
+        if not Match:\r
+            # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method\r
+            Parser(self)\r
+            return\r
+\r
+        TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)\r
+        # Syntax check\r
+        if not TokenList[0]:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if len(TokenList) < 2:\r
+            TokenList.append('')\r
+\r
+        Type = Match.group(1)\r
+        Name, Value = TokenList\r
+        # Global macros can be only defined via environment variable\r
+        if Name in GlobalData.gGlobalDefines:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        # Only upper case letters, digit and '_' are allowed\r
+        if not gMacroNamePattern.match(Name):\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        Value = ReplaceMacro(Value, self._Macros)\r
+        if Type in self.DataType:\r
+            self._ItemType = self.DataType[Type]\r
+        else:\r
+            self._ItemType = MODEL_META_DATA_DEFINE\r
+        # DEFINE defined macros\r
+        if Type == TAB_DSC_DEFINES_DEFINE:\r
+            #\r
+            # First judge whether this DEFINE is in conditional directive statements or not.\r
+            #\r
+            if isinstance(self, DscParser) and self._InDirective > -1:\r
+                pass\r
+            else:\r
+                if isinstance(self, DecParser):\r
+                    if MODEL_META_DATA_HEADER in self._SectionType:\r
+                        self._FileLocalMacros[Name] = Value\r
+                    else:\r
+                        self._ConstructSectionMacroDict(Name, Value)\r
+                elif self._SectionType == MODEL_META_DATA_HEADER:\r
+                    self._FileLocalMacros[Name] = Value\r
+                else:\r
+                    self._ConstructSectionMacroDict(Name, Value)\r
+\r
+        # EDK_GLOBAL defined macros\r
+        elif not isinstance(self, DscParser):\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        elif self._SectionType != MODEL_META_DATA_HEADER:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        self._ValueList = [Type, Name, Value]\r
+\r
+    return MacroParser\r
+\r
+## Base class of parser\r
+#\r
+#  This class is used for derivation purpose. The specific parser for one kind\r
+# type file must derive this class and implement some public interfaces.\r
+#\r
+#   @param      FilePath        The path of platform description file\r
+#   @param      FileType        The raw data of DSC file\r
+#   @param      Table           Database used to retrieve module/package information\r
+#   @param      Macros          Macros used for replacement in file\r
+#   @param      Owner           Owner ID (for sub-section parsing)\r
+#   @param      From            ID from which the data comes (for !INCLUDE directive)\r
+#\r
+class MetaFileParser(object):\r
+    # data type (file content) for specific file type\r
+    DataType = {}\r
+\r
+    # Parser objects used to implement singleton\r
+    MetaFiles = {}\r
+\r
+    ## Factory method\r
+    #\r
+    # One file, one parser object. This factory method makes sure that there's\r
+    # only one object constructed for one meta file.\r
+    #\r
+    #   @param  Class           class object of real AutoGen class\r
+    #                           (InfParser, DecParser or DscParser)\r
+    #   @param  FilePath        The path of meta file\r
+    #   @param  *args           The specific class related parameters\r
+    #   @param  **kwargs        The specific class related dict parameters\r
+    #\r
+    def __new__(Class, FilePath, *args, **kwargs):\r
+        if FilePath in Class.MetaFiles:\r
+            return Class.MetaFiles[FilePath]\r
+        else:\r
+            ParserObject = super(MetaFileParser, Class).__new__(Class)\r
+            Class.MetaFiles[FilePath] = ParserObject\r
+            return ParserObject\r
+\r
+    ## Constructor of MetaFileParser\r
+    #\r
+    #  Initialize object of MetaFileParser\r
+    #\r
+    #   @param      FilePath        The path of platform description file\r
+    #   @param      FileType        The raw data of DSC file\r
+    #   @param      Arch            Default Arch value for filtering sections\r
+    #   @param      Table           Database used to retrieve module/package information\r
+    #   @param      Owner           Owner ID (for sub-section parsing)\r
+    #   @param      From            ID from which the data comes (for !INCLUDE directive)\r
+    #\r
+    def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
+        self._Table = Table\r
+        self._RawTable = Table\r
+        self._Arch = Arch\r
+        self._FileType = FileType\r
+        self.MetaFile = FilePath\r
+        self._FileDir = self.MetaFile.Dir\r
+        self._Defines = {}\r
+        self._FileLocalMacros = {}\r
+        self._SectionsMacroDict = defaultdict(dict)\r
+\r
+        # for recursive parsing\r
+        self._Owner = [Owner]\r
+        self._From = From\r
+\r
+        # parsr status for parsing\r
+        self._ValueList = ['', '', '', '', '']\r
+        self._Scope = []\r
+        self._LineIndex = 0\r
+        self._CurrentLine = ''\r
+        self._SectionType = MODEL_UNKNOWN\r
+        self._SectionName = ''\r
+        self._InSubsection = False\r
+        self._SubsectionType = MODEL_UNKNOWN\r
+        self._SubsectionName = ''\r
+        self._ItemType = MODEL_UNKNOWN\r
+        self._LastItem = -1\r
+        self._Enabled = 0\r
+        self._Finished = False\r
+        self._PostProcessed = False\r
+        # Different version of meta-file has different way to parse.\r
+        self._Version = 0\r
+        self._GuidDict = {}  # for Parser PCD value {GUID(gTokeSpaceGuidName)}\r
+\r
+    ## Store the parsed data in table\r
+    def _Store(self, *Args):\r
+        return self._Table.Insert(*Args)\r
+\r
+    ## Virtual method for starting parse\r
+    def Start(self):\r
+        raise NotImplementedError\r
+\r
+    ## Notify a post-process is needed\r
+    def DoPostProcess(self):\r
+        self._PostProcessed = False\r
+\r
+    ## Set parsing complete flag in both class and table\r
+    def _Done(self):\r
+        self._Finished = True\r
+        ## Do not set end flag when processing included files\r
+        if self._From == -1:\r
+            self._Table.SetEndFlag()\r
+\r
+    def _PostProcess(self):\r
+        self._PostProcessed = True\r
+\r
+    ## Get the parse complete flag\r
+    def _GetFinished(self):\r
+        return self._Finished\r
+\r
+    ## Set the complete flag\r
+    def _SetFinished(self, Value):\r
+        self._Finished = Value\r
+\r
+    ## Remove records that do not match given Filter Arch\r
+    def _FilterRecordList(self, RecordList, FilterArch):\r
+        NewRecordList = []\r
+        for Record in RecordList:\r
+            Arch = Record[3]\r
+            if Arch == TAB_ARCH_COMMON or Arch == FilterArch:\r
+                NewRecordList.append(Record)\r
+        return NewRecordList\r
+\r
+    ## Use [] style to query data in table, just for readability\r
+    #\r
+    #   DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]\r
+    #\r
+    def __getitem__(self, DataInfo):\r
+        if not isinstance(DataInfo, type(())):\r
+            DataInfo = (DataInfo,)\r
+\r
+        # Parse the file first, if necessary\r
+        if not self._Finished:\r
+            if self._RawTable.IsIntegrity():\r
+                self._Finished = True\r
+            else:\r
+                self._Table = self._RawTable\r
+                self._PostProcessed = False\r
+                self.Start()\r
+\r
+        # No specific ARCH or Platform given, use raw data\r
+        if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):\r
+            return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)\r
+\r
+        # Do post-process if necessary\r
+        if not self._PostProcessed:\r
+            self._PostProcess()\r
+\r
+        return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])\r
+\r
+    ## Data parser for the common format in different type of file\r
+    #\r
+    #   The common format in the meatfile is like\r
+    #\r
+    #       xxx1 | xxx2 | xxx3\r
+    #\r
+    @ParseMacro\r
+    def _CommonParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+\r
+    ## Data parser for the format in which there's path\r
+    #\r
+    #   Only path can have macro used. So we need to replace them before use.\r
+    #\r
+    @ParseMacro\r
+    def _PathParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+        # Don't do macro replacement for dsc file at this point\r
+        if not isinstance(self, DscParser):\r
+            Macros = self._Macros\r
+            self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]\r
+\r
+    ## Skip unsupported data\r
+    def _Skip(self):\r
+        EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,\r
+                        Line=self._LineIndex + 1, ExtraData=self._CurrentLine);\r
+        self._ValueList[0:1] = [self._CurrentLine]\r
+\r
+    ## Skip unsupported data for UserExtension Section\r
+    def _SkipUserExtension(self):\r
+        self._ValueList[0:1] = [self._CurrentLine]\r
+\r
+    ## Section header parser\r
+    #\r
+    #   The section header is always in following format:\r
+    #\r
+    #       [section_name.arch<.platform|module_type>]\r
+    #\r
+    def _SectionHeaderParser(self):\r
+        self._Scope = []\r
+        self._SectionName = ''\r
+        ArchList = set()\r
+        for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):\r
+            if Item == '':\r
+                continue\r
+            ItemList = GetSplitValueList(Item, TAB_SPLIT, 3)\r
+            # different section should not mix in one section\r
+            if self._SectionName != '' and self._SectionName != ItemList[0].upper():\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
+            self._SectionName = ItemList[0].upper()\r
+            if self._SectionName in self.DataType:\r
+                self._SectionType = self.DataType[self._SectionName]\r
+                # Check if the section name is valid\r
+                if self._SectionName not in SECTIONS_HAVE_ITEM_AFTER_ARCH_SET and len(ItemList) > 3:\r
+                    EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
+                                    self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
+            elif self._Version >= 0x00010005:\r
+                EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
+                                self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
+            else:\r
+                self._SectionType = MODEL_UNKNOWN\r
+\r
+            # S1 is always Arch\r
+            if len(ItemList) > 1:\r
+                S1 = ItemList[1].upper()\r
+            else:\r
+                S1 = TAB_ARCH_COMMON\r
+            ArchList.add(S1)\r
+\r
+            # S2 may be Platform or ModuleType\r
+            if len(ItemList) > 2:\r
+                if self._SectionName.upper() in SECTIONS_HAVE_ITEM_PCD_SET:\r
+                    S2 = ItemList[2]\r
+                else:\r
+                    S2 = ItemList[2].upper()\r
+            else:\r
+                S2 = TAB_COMMON\r
+            if len(ItemList) > 3:\r
+                S3 = ItemList[3]\r
+            else:\r
+                S3 = TAB_COMMON\r
+            self._Scope.append([S1, S2, S3])\r
+\r
+        # 'COMMON' must not be used with specific ARCHs at the same section\r
+        if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
+        # If the section information is needed later, it should be stored in database\r
+        self._ValueList[0] = self._SectionName\r
+\r
+    ## [defines] section parser\r
+    @ParseMacro\r
+    def _DefineParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
+        self._ValueList[1:len(TokenList)] = TokenList\r
+        if not self._ValueList[1]:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if not self._ValueList[2]:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
+        Name, Value = self._ValueList[1], self._ValueList[2]\r
+        MacroUsed = GlobalData.gMacroRefPattern.findall(Value)\r
+        if len(MacroUsed) != 0:\r
+            for Macro in MacroUsed:\r
+                if Macro in GlobalData.gGlobalDefines:\r
+                    EdkLogger.error("Parser", FORMAT_INVALID, "Global macro %s is not permitted." % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+            else:\r
+                EdkLogger.error("Parser", FORMAT_INVALID, "%s not defined" % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        # Sometimes, we need to make differences between EDK and EDK2 modules\r
+        if Name == 'INF_VERSION':\r
+            if hexVersionPattern.match(Value):\r
+                self._Version = int(Value, 0)\r
+            elif decVersionPattern.match(Value):\r
+                ValueList = Value.split('.')\r
+                Major = '%04o' % int(ValueList[0], 0)\r
+                Minor = '%04o' % int(ValueList[1], 0)\r
+                self._Version = int('0x' + Major + Minor, 0)\r
+            else:\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",\r
+                                ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        if isinstance(self, InfParser) and self._Version < 0x00010005:\r
+            # EDK module allows using defines as macros\r
+            self._FileLocalMacros[Name] = Value\r
+        self._Defines[Name] = Value\r
+\r
+    ## [BuildOptions] section parser\r
+    @ParseMacro\r
+    def _BuildOptionParser(self):\r
+        self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
+        TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
+        if len(TokenList2) == 2:\r
+            self._ValueList[0] = TokenList2[0]              # toolchain family\r
+            self._ValueList[1] = TokenList2[1]              # keys\r
+        else:\r
+            self._ValueList[1] = TokenList[0]\r
+        if len(TokenList) == 2 and not isinstance(self, DscParser): # value\r
+            self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)\r
+\r
+        if self._ValueList[1].count('_') != 4:\r
+            EdkLogger.error(\r
+                'Parser',\r
+                FORMAT_INVALID,\r
+                "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
+                ExtraData=self._CurrentLine,\r
+                File=self.MetaFile,\r
+                Line=self._LineIndex + 1\r
+                )\r
+    def GetValidExpression(self, TokenSpaceGuid, PcdCName):\r
+        return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)\r
+    def _GetMacros(self):\r
+        Macros = {}\r
+        Macros.update(self._FileLocalMacros)\r
+        Macros.update(self._GetApplicableSectionMacro())\r
+        return Macros\r
+\r
+    ## Construct section Macro dict\r
+    def _ConstructSectionMacroDict(self, Name, Value):\r
+        ScopeKey = [(Scope[0], Scope[1], Scope[2]) for Scope in self._Scope]\r
+        ScopeKey = tuple(ScopeKey)\r
+        #\r
+        # DecParser SectionType is a list, will contain more than one item only in Pcd Section\r
+        # As Pcd section macro usage is not alllowed, so here it is safe\r
+        #\r
+        if isinstance(self, DecParser):\r
+            SectionDictKey = self._SectionType[0], ScopeKey\r
+        else:\r
+            SectionDictKey = self._SectionType, ScopeKey\r
+\r
+        self._SectionsMacroDict[SectionDictKey][Name] = Value\r
+\r
+    ## Get section Macros that are applicable to current line, which may come from other sections\r
+    ## that share the same name while scope is wider\r
+    def _GetApplicableSectionMacro(self):\r
+        Macros = {}\r
+\r
+        ComComMacroDict = {}\r
+        ComSpeMacroDict = {}\r
+        SpeSpeMacroDict = {}\r
+\r
+        ActiveSectionType = self._SectionType\r
+        if isinstance(self, DecParser):\r
+            ActiveSectionType = self._SectionType[0]\r
+\r
+        for (SectionType, Scope) in self._SectionsMacroDict:\r
+            if SectionType != ActiveSectionType:\r
+                continue\r
+\r
+            for ActiveScope in self._Scope:\r
+                Scope0, Scope1, Scope2= ActiveScope[0], ActiveScope[1], ActiveScope[2]\r
+                if(Scope0, Scope1, Scope2) not in Scope:\r
+                    break\r
+            else:\r
+                SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])\r
+\r
+            for ActiveScope in self._Scope:\r
+                Scope0, Scope1, Scope2 = ActiveScope[0], ActiveScope[1], ActiveScope[2]\r
+                if(Scope0, Scope1, Scope2) not in Scope and (Scope0, TAB_COMMON, TAB_COMMON) not in Scope and (TAB_COMMON, Scope1, TAB_COMMON) not in Scope:\r
+                    break\r
+            else:\r
+                ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])\r
+\r
+            if (TAB_COMMON, TAB_COMMON, TAB_COMMON) in Scope:\r
+                ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])\r
+\r
+        Macros.update(ComComMacroDict)\r
+        Macros.update(ComSpeMacroDict)\r
+        Macros.update(SpeSpeMacroDict)\r
+\r
+        return Macros\r
+\r
+    _SectionParser = {}\r
+    Finished = property(_GetFinished, _SetFinished)\r
+    _Macros = property(_GetMacros)\r
+\r
+\r
+## INF file parser class\r
+#\r
+#   @param      FilePath        The path of platform description file\r
+#   @param      FileType        The raw data of DSC file\r
+#   @param      Table           Database used to retrieve module/package information\r
+#   @param      Macros          Macros used for replacement in file\r
+#\r
+class InfParser(MetaFileParser):\r
+    # INF file supported data types (one type per section)\r
+    DataType = {\r
+        TAB_UNKNOWN.upper() : MODEL_UNKNOWN,\r
+        TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
+        TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
+        TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,\r
+        TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
+        TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,\r
+        TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
+        TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,\r
+        TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,\r
+        TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
+        TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
+        TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,\r
+        TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,\r
+        TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,\r
+        TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,\r
+        TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
+        TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
+        TAB_PPIS.upper() : MODEL_EFI_PPI,\r
+        TAB_DEPEX.upper() : MODEL_EFI_DEPEX,\r
+        TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,\r
+        TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION\r
+    }\r
+\r
+    ## Constructor of InfParser\r
+    #\r
+    #  Initialize object of InfParser\r
+    #\r
+    #   @param      FilePath        The path of module description file\r
+    #   @param      FileType        The raw data of DSC file\r
+    #   @param      Arch            Default Arch value for filtering sections\r
+    #   @param      Table           Database used to retrieve module/package information\r
+    #\r
+    def __init__(self, FilePath, FileType, Arch, Table):\r
+        # prevent re-initialization\r
+        if hasattr(self, "_Table"):\r
+            return\r
+        MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)\r
+        self.PcdsDict = {}\r
+\r
+    ## Parser starter\r
+    def Start(self):\r
+        NmakeLine = ''\r
+        Content = ''\r
+        try:\r
+            Content = open(str(self.MetaFile), 'r').readlines()\r
+        except:\r
+            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
+\r
+        # parse the file line by line\r
+        IsFindBlockComment = False\r
+        GetHeaderComment = False\r
+        TailComments = []\r
+        SectionComments = []\r
+        Comments = []\r
+\r
+        for Index in range(0, len(Content)):\r
+            # skip empty, commented, block commented lines\r
+            Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)\r
+            NextLine = ''\r
+            if Index + 1 < len(Content):\r
+                NextLine, NextComment = CleanString2(Content[Index + 1])\r
+            if Line == '':\r
+                if Comment:\r
+                    Comments.append((Comment, Index + 1))\r
+                elif GetHeaderComment:\r
+                    SectionComments.extend(Comments)\r
+                    Comments = []\r
+                continue\r
+            if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:\r
+                IsFindBlockComment = True\r
+                continue\r
+            if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:\r
+                IsFindBlockComment = False\r
+                continue\r
+            if IsFindBlockComment:\r
+                continue\r
+\r
+            self._LineIndex = Index\r
+            self._CurrentLine = Line\r
+\r
+            # section header\r
+            if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
+                if not GetHeaderComment:\r
+                    for Cmt, LNo in Comments:\r
+                        self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', TAB_COMMON,\r
+                                    TAB_COMMON, self._Owner[-1], LNo, -1, LNo, -1, 0)\r
+                    GetHeaderComment = True\r
+                else:\r
+                    TailComments.extend(SectionComments + Comments)\r
+                Comments = []\r
+                self._SectionHeaderParser()\r
+                # Check invalid sections\r
+                if self._Version < 0x00010005:\r
+                    if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,\r
+                                             MODEL_EFI_LIBRARY_CLASS,\r
+                                             MODEL_META_DATA_PACKAGE,\r
+                                             MODEL_PCD_FIXED_AT_BUILD,\r
+                                             MODEL_PCD_PATCHABLE_IN_MODULE,\r
+                                             MODEL_PCD_FEATURE_FLAG,\r
+                                             MODEL_PCD_DYNAMIC_EX,\r
+                                             MODEL_PCD_DYNAMIC,\r
+                                             MODEL_EFI_GUID,\r
+                                             MODEL_EFI_PROTOCOL,\r
+                                             MODEL_EFI_PPI,\r
+                                             MODEL_META_DATA_USER_EXTENSION]:\r
+                        EdkLogger.error('Parser', FORMAT_INVALID,\r
+                                        "Section [%s] is not allowed in inf file without version" % (self._SectionName),\r
+                                        ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+                elif self._SectionType in [MODEL_EFI_INCLUDE,\r
+                                           MODEL_EFI_LIBRARY_INSTANCE,\r
+                                           MODEL_META_DATA_NMAKE]:\r
+                    EdkLogger.error('Parser', FORMAT_INVALID,\r
+                                    "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),\r
+                                    ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+                continue\r
+            # merge two lines specified by '\' in section NMAKE\r
+            elif self._SectionType == MODEL_META_DATA_NMAKE:\r
+                if Line[-1] == '\\':\r
+                    if NextLine == '':\r
+                        self._CurrentLine = NmakeLine + Line[0:-1]\r
+                        NmakeLine = ''\r
+                    else:\r
+                        if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:\r
+                            self._CurrentLine = NmakeLine + Line[0:-1]\r
+                            NmakeLine = ''\r
+                        else:\r
+                            NmakeLine = NmakeLine + ' ' + Line[0:-1]\r
+                            continue\r
+                else:\r
+                    self._CurrentLine = NmakeLine + Line\r
+                    NmakeLine = ''\r
+\r
+            # section content\r
+            self._ValueList = ['', '', '']\r
+            # parse current line, result will be put in self._ValueList\r
+            self._SectionParser[self._SectionType](self)\r
+            if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
+                self._ItemType = -1\r
+                Comments = []\r
+                continue\r
+            if Comment:\r
+                Comments.append((Comment, Index + 1))\r
+            if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:\r
+                CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)\r
+            #\r
+            # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,\r
+            # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
+            #\r
+            for Arch, Platform, _ in self._Scope:\r
+                LastItem = self._Store(self._SectionType,\r
+                            self._ValueList[0],\r
+                            self._ValueList[1],\r
+                            self._ValueList[2],\r
+                            Arch,\r
+                            Platform,\r
+                            self._Owner[-1],\r
+                            self._LineIndex + 1,\r
+                            - 1,\r
+                            self._LineIndex + 1,\r
+                            - 1,\r
+                            0\r
+                            )\r
+                for Comment, LineNo in Comments:\r
+                    self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,\r
+                                LastItem, LineNo, -1, LineNo, -1, 0)\r
+            Comments = []\r
+            SectionComments = []\r
+        TailComments.extend(SectionComments + Comments)\r
+        if IsFindBlockComment:\r
+            EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",\r
+                            File=self.MetaFile)\r
+\r
+        # If there are tail comments in INF file, save to database whatever the comments are\r
+        for Comment in TailComments:\r
+            self._Store(MODEL_META_DATA_TAIL_COMMENT, Comment[0], '', '', TAB_COMMON,\r
+                                TAB_COMMON, self._Owner[-1], -1, -1, -1, -1, 0)\r
+        self._Done()\r
+\r
+    ## Data parser for the format in which there's path\r
+    #\r
+    #   Only path can have macro used. So we need to replace them before use.\r
+    #\r
+    def _IncludeParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+        Macros = self._Macros\r
+        if Macros:\r
+            for Index in range(0, len(self._ValueList)):\r
+                Value = self._ValueList[Index]\r
+                if not Value:\r
+                    continue\r
+\r
+                if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:\r
+                    Value = '$(EDK_SOURCE)' + Value[17:]\r
+                if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:\r
+                    pass\r
+                elif Value.startswith('.'):\r
+                    pass\r
+                elif Value.startswith('$('):\r
+                    pass\r
+                else:\r
+                    Value = '$(EFI_SOURCE)/' + Value\r
+\r
+                self._ValueList[Index] = ReplaceMacro(Value, Macros)\r
+\r
+    ## Parse [Sources] section\r
+    #\r
+    #   Only path can have macro used. So we need to replace them before use.\r
+    #\r
+    @ParseMacro\r
+    def _SourceFileParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+        Macros = self._Macros\r
+        # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'\r
+        if 'COMPONENT_TYPE' in Macros:\r
+            if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':\r
+                self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]\r
+        if self._Defines['BASE_NAME'] == 'Microcode':\r
+            pass\r
+        self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]\r
+\r
+    ## Parse [Binaries] section\r
+    #\r
+    #   Only path can have macro used. So we need to replace them before use.\r
+    #\r
+    @ParseMacro\r
+    def _BinaryFileParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)\r
+        if len(TokenList) < 2:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",\r
+                            ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if not TokenList[0]:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",\r
+                            ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if not TokenList[1]:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",\r
+                            ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+        self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)\r
+\r
+    ## [nmake] section parser (Edk.x style only)\r
+    def _NmakeParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+        # remove macros\r
+        self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)\r
+        # remove self-reference in macro setting\r
+        #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})\r
+\r
+    ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser\r
+    @ParseMacro\r
+    def _PcdParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
+        ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
+        if len(ValueList) != 2:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",\r
+                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        self._ValueList[0:1] = ValueList\r
+        if len(TokenList) > 1:\r
+            self._ValueList[2] = TokenList[1]\r
+        if self._ValueList[0] == '' or self._ValueList[1] == '':\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
+                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
+        if self._ValueList[2] != '':\r
+            InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
+            if InfPcdValueList[0] in ['True', 'true', 'TRUE']:\r
+                self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);\r
+            elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:\r
+                self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);\r
+        if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:\r
+            self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType\r
+        elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",\r
+                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+    ## [depex] section parser\r
+    @ParseMacro\r
+    def _DepexParser(self):\r
+        self._ValueList[0:1] = [self._CurrentLine]\r
+\r
+    _SectionParser = {\r
+        MODEL_UNKNOWN                   :   MetaFileParser._Skip,\r
+        MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,\r
+        MODEL_META_DATA_BUILD_OPTION    :   MetaFileParser._BuildOptionParser,\r
+        MODEL_EFI_INCLUDE               :   _IncludeParser, # for Edk.x modules\r
+        MODEL_EFI_LIBRARY_INSTANCE      :   MetaFileParser._CommonParser, # for Edk.x modules\r
+        MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,\r
+        MODEL_META_DATA_PACKAGE         :   MetaFileParser._PathParser,\r
+        MODEL_META_DATA_NMAKE           :   _NmakeParser, # for Edk.x modules\r
+        MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,\r
+        MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,\r
+        MODEL_PCD_FEATURE_FLAG          :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC_EX            :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC               :   _PcdParser,\r
+        MODEL_EFI_SOURCE_FILE           :   _SourceFileParser,\r
+        MODEL_EFI_GUID                  :   MetaFileParser._CommonParser,\r
+        MODEL_EFI_PROTOCOL              :   MetaFileParser._CommonParser,\r
+        MODEL_EFI_PPI                   :   MetaFileParser._CommonParser,\r
+        MODEL_EFI_DEPEX                 :   _DepexParser,\r
+        MODEL_EFI_BINARY_FILE           :   _BinaryFileParser,\r
+        MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._SkipUserExtension,\r
+    }\r
+\r
+## DSC file parser class\r
+#\r
+#   @param      FilePath        The path of platform description file\r
+#   @param      FileType        The raw data of DSC file\r
+#   @param      Table           Database used to retrieve module/package information\r
+#   @param      Macros          Macros used for replacement in file\r
+#   @param      Owner           Owner ID (for sub-section parsing)\r
+#   @param      From            ID from which the data comes (for !INCLUDE directive)\r
+#\r
+class DscParser(MetaFileParser):\r
+    # DSC file supported data types (one type per section)\r
+    DataType = {\r
+        TAB_SKUIDS.upper()                          :   MODEL_EFI_SKU_ID,\r
+        TAB_DEFAULT_STORES.upper()                  :   MODEL_EFI_DEFAULT_STORES,\r
+        TAB_LIBRARIES.upper()                       :   MODEL_EFI_LIBRARY_INSTANCE,\r
+        TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,\r
+        TAB_BUILD_OPTIONS.upper()                   :   MODEL_META_DATA_BUILD_OPTION,\r
+        TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,\r
+        TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,\r
+        TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,\r
+        TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper()       :   MODEL_PCD_DYNAMIC_DEFAULT,\r
+        TAB_PCDS_DYNAMIC_HII_NULL.upper()           :   MODEL_PCD_DYNAMIC_HII,\r
+        TAB_PCDS_DYNAMIC_VPD_NULL.upper()           :   MODEL_PCD_DYNAMIC_VPD,\r
+        TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper()    :   MODEL_PCD_DYNAMIC_EX_DEFAULT,\r
+        TAB_PCDS_DYNAMIC_EX_HII_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_HII,\r
+        TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_VPD,\r
+        TAB_COMPONENTS.upper()                      :   MODEL_META_DATA_COMPONENT,\r
+        TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() :   MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,\r
+        TAB_DSC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,\r
+        TAB_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,\r
+        TAB_DSC_DEFINES_EDKGLOBAL                   :   MODEL_META_DATA_GLOBAL_DEFINE,\r
+        TAB_INCLUDE.upper()                         :   MODEL_META_DATA_INCLUDE,\r
+        TAB_IF.upper()                              :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
+        TAB_IF_DEF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
+        TAB_IF_N_DEF.upper()                        :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,\r
+        TAB_ELSE_IF.upper()                         :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,\r
+        TAB_ELSE.upper()                            :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,\r
+        TAB_END_IF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,\r
+        TAB_USER_EXTENSIONS.upper()                 :   MODEL_META_DATA_USER_EXTENSION,\r
+        TAB_ERROR.upper()                           :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,\r
+    }\r
+\r
+    # Valid names in define section\r
+    DefineKeywords = [\r
+        "DSC_SPECIFICATION",\r
+        "PLATFORM_NAME",\r
+        "PLATFORM_GUID",\r
+        "PLATFORM_VERSION",\r
+        "SKUID_IDENTIFIER",\r
+        "PCD_INFO_GENERATION",\r
+        "PCD_VAR_CHECK_GENERATION",\r
+        "SUPPORTED_ARCHITECTURES",\r
+        "BUILD_TARGETS",\r
+        "OUTPUT_DIRECTORY",\r
+        "FLASH_DEFINITION",\r
+        "BUILD_NUMBER",\r
+        "RFC_LANGUAGES",\r
+        "ISO_LANGUAGES",\r
+        "TIME_STAMP_FILE",\r
+        "VPD_TOOL_GUID",\r
+        "FIX_LOAD_TOP_MEMORY_ADDRESS",\r
+        "PREBUILD",\r
+        "POSTBUILD"\r
+    ]\r
+\r
+    SubSectionDefineKeywords = [\r
+        "FILE_GUID"\r
+    ]\r
+\r
+    SymbolPattern = ValueExpression.SymbolPattern\r
+\r
+    IncludedFiles = set()\r
+\r
+    ## Constructor of DscParser\r
+    #\r
+    #  Initialize object of DscParser\r
+    #\r
+    #   @param      FilePath        The path of platform description file\r
+    #   @param      FileType        The raw data of DSC file\r
+    #   @param      Arch            Default Arch value for filtering sections\r
+    #   @param      Table           Database used to retrieve module/package information\r
+    #   @param      Owner           Owner ID (for sub-section parsing)\r
+    #   @param      From            ID from which the data comes (for !INCLUDE directive)\r
+    #\r
+    def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
+        # prevent re-initialization\r
+        if hasattr(self, "_Table") and self._Table is Table:\r
+            return\r
+        MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)\r
+        self._Version = 0x00010005  # Only EDK2 dsc file is supported\r
+        # to store conditional directive evaluation result\r
+        self._DirectiveStack = []\r
+        self._DirectiveEvalStack = []\r
+        self._Enabled = 1\r
+\r
+        #\r
+        # Specify whether current line is in uncertain condition\r
+        #\r
+        self._InDirective = -1\r
+\r
+        # Final valid replacable symbols\r
+        self._Symbols = {}\r
+        #\r
+        #  Map the ID between the original table and new table to track\r
+        #  the owner item\r
+        #\r
+        self._IdMapping = {-1:-1}\r
+\r
+    ## Parser starter\r
+    def Start(self):\r
+        Content = ''\r
+        try:\r
+            Content = open(str(self.MetaFile), 'r').readlines()\r
+        except:\r
+            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
+\r
+        OwnerId = {}\r
+        for Index in range(0, len(Content)):\r
+            Line = CleanString(Content[Index])\r
+            # skip empty line\r
+            if Line == '':\r
+                continue\r
+\r
+            self._CurrentLine = Line\r
+            self._LineIndex = Index\r
+            if self._InSubsection and self._Owner[-1] == -1:\r
+                self._Owner.append(self._LastItem)\r
+\r
+            # section header\r
+            if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
+                self._SectionType = MODEL_META_DATA_SECTION_HEADER\r
+            # subsection ending\r
+            elif Line[0] == '}' and self._InSubsection:\r
+                self._InSubsection = False\r
+                self._SubsectionType = MODEL_UNKNOWN\r
+                self._SubsectionName = ''\r
+                self._Owner[-1] = -1\r
+                OwnerId.clear()\r
+                continue\r
+            # subsection header\r
+            elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:\r
+                self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER\r
+            # directive line\r
+            elif Line[0] == '!':\r
+                TokenList = GetSplitValueList(Line, ' ', 1)\r
+                if TokenList[0] == TAB_INCLUDE:\r
+                    for Arch, ModuleType, DefaultStore in self._Scope:\r
+                        if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
+                            self._Owner[-1] = OwnerId[Arch]\r
+                        self._DirectiveParser()\r
+                else:\r
+                    self._DirectiveParser()\r
+                continue\r
+            if Line[0] == TAB_OPTION_START and not self._InSubsection:\r
+                EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)\r
+\r
+            if self._InSubsection:\r
+                SectionType = self._SubsectionType\r
+            else:\r
+                SectionType = self._SectionType\r
+            self._ItemType = SectionType\r
+\r
+            self._ValueList = ['', '', '']\r
+            self._SectionParser[SectionType](self)\r
+            if self._ValueList is None:\r
+                continue\r
+            #\r
+            # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
+            # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
+            #\r
+            for Arch, ModuleType, DefaultStore in self._Scope:\r
+                Owner = self._Owner[-1]\r
+                if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
+                    Owner = OwnerId[Arch]\r
+                self._LastItem = self._Store(\r
+                                        self._ItemType,\r
+                                        self._ValueList[0],\r
+                                        self._ValueList[1],\r
+                                        self._ValueList[2],\r
+                                        Arch,\r
+                                        ModuleType,\r
+                                        DefaultStore,\r
+                                        Owner,\r
+                                        self._From,\r
+                                        self._LineIndex + 1,\r
+                                        - 1,\r
+                                        self._LineIndex + 1,\r
+                                        - 1,\r
+                                        self._Enabled\r
+                                        )\r
+                if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:\r
+                    OwnerId[Arch] = self._LastItem\r
+\r
+        if self._DirectiveStack:\r
+            Type, Line, Text = self._DirectiveStack[-1]\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",\r
+                            ExtraData=Text, File=self.MetaFile, Line=Line)\r
+        self._Done()\r
+\r
+    ## <subsection_header> parser\r
+    def _SubsectionHeaderParser(self):\r
+        self._SubsectionName = self._CurrentLine[1:-1].upper()\r
+        if self._SubsectionName in self.DataType:\r
+            self._SubsectionType = self.DataType[self._SubsectionName]\r
+        else:\r
+            self._SubsectionType = MODEL_UNKNOWN\r
+            EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,\r
+                           Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
+        self._ValueList[0] = self._SubsectionName\r
+\r
+    ## Directive statement parser\r
+    def _DirectiveParser(self):\r
+        self._ValueList = ['', '', '']\r
+        TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+\r
+        # Syntax check\r
+        DirectiveName = self._ValueList[0].upper()\r
+        if DirectiveName not in self.DataType:\r
+            EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:\r
+            self._InDirective += 1\r
+\r
+        if DirectiveName in ['!ENDIF']:\r
+            self._InDirective -= 1\r
+\r
+        if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':\r
+            EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1,\r
+                            ExtraData=self._CurrentLine)\r
+\r
+        ItemType = self.DataType[DirectiveName]\r
+        Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]\r
+        if ItemType == MODEL_META_DATA_INCLUDE:\r
+            Scope = self._Scope\r
+        elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:\r
+            Scope = self._Scope\r
+        if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
+            # Remove all directives between !if and !endif, including themselves\r
+            while self._DirectiveStack:\r
+                # Remove any !else or !elseif\r
+                DirectiveInfo = self._DirectiveStack.pop()\r
+                if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
+                                        MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
+                                        MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
+                    break\r
+            else:\r
+                EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1,\r
+                                ExtraData=self._CurrentLine)\r
+        elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:\r
+            # Break if there's a !else is followed by a !elseif\r
+            if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \\r
+               self._DirectiveStack and \\r
+               self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
+                EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1,\r
+                                ExtraData=self._CurrentLine)\r
+            self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))\r
+\r
+        #\r
+        # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
+        # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
+        #\r
+        for Arch, ModuleType, DefaultStore in Scope:\r
+            self._LastItem = self._Store(\r
+                                    ItemType,\r
+                                    self._ValueList[0],\r
+                                    self._ValueList[1],\r
+                                    self._ValueList[2],\r
+                                    Arch,\r
+                                    ModuleType,\r
+                                    DefaultStore,\r
+                                    self._Owner[-1],\r
+                                    self._From,\r
+                                    self._LineIndex + 1,\r
+                                    - 1,\r
+                                    self._LineIndex + 1,\r
+                                    - 1,\r
+                                    0\r
+                                    )\r
+\r
+    ## [defines] section parser\r
+    @ParseMacro\r
+    def _DefineParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
+        self._ValueList[1:len(TokenList)] = TokenList\r
+\r
+        # Syntax check\r
+        if not self._ValueList[1]:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if not self._ValueList[2]:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if (not self._ValueList[1] in self.DefineKeywords and\r
+            (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
+            EdkLogger.error('Parser', FORMAT_INVALID,\r
+                            "Unknown keyword found: %s. "\r
+                            "If this is a macro you must "\r
+                            "add it as a DEFINE in the DSC" % self._ValueList[1],\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if not self._InSubsection:\r
+            self._Defines[self._ValueList[1]] = self._ValueList[2]\r
+        self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]\r
+\r
+    @ParseMacro\r
+    def _SkuIdParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
+        if len(TokenList) not in (2, 3):\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+    @ParseMacro\r
+    def _DefaultStoresParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
+        if len(TokenList) != 2:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+\r
+    ## Parse Edk style of library modules\r
+    @ParseMacro\r
+    def _LibraryInstanceParser(self):\r
+        self._ValueList[0] = self._CurrentLine\r
+\r
+    ## PCD sections parser\r
+    #\r
+    #   [PcdsFixedAtBuild]\r
+    #   [PcdsPatchableInModule]\r
+    #   [PcdsFeatureFlag]\r
+    #   [PcdsDynamicEx\r
+    #   [PcdsDynamicExDefault]\r
+    #   [PcdsDynamicExVpd]\r
+    #   [PcdsDynamicExHii]\r
+    #   [PcdsDynamic]\r
+    #   [PcdsDynamicDefault]\r
+    #   [PcdsDynamicVpd]\r
+    #   [PcdsDynamicHii]\r
+    #\r
+    @ParseMacro\r
+    def _PcdParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
+        self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
+        PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
+        if len(PcdNameTockens) == 2:\r
+            self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]\r
+        elif len(PcdNameTockens) == 3:\r
+            self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]\r
+        elif len(PcdNameTockens) > 3:\r
+            self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])\r
+        if len(TokenList) == 2:\r
+            self._ValueList[2] = TokenList[1]\r
+        if self._ValueList[0] == '' or self._ValueList[1] == '':\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
+                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if self._ValueList[2] == '':\r
+            #\r
+            # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default\r
+            #\r
+            if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):\r
+                return\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",\r
+                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD\r
+        ValueList = GetSplitValueList(self._ValueList[2])\r
+        if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \\r
+                              and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string\r
+        if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:\r
+            DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
+            if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
+        DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
+        if DscPcdValueList[0] in ['True', 'true', 'TRUE']:\r
+            self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);\r
+        elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:\r
+            self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);\r
+\r
+\r
+    ## [components] section parser\r
+    @ParseMacro\r
+    def _ComponentParser(self):\r
+        if self._CurrentLine[-1] == '{':\r
+            self._ValueList[0] = self._CurrentLine[0:-1].strip()\r
+            self._InSubsection = True\r
+            self._SubsectionType = MODEL_UNKNOWN\r
+        else:\r
+            self._ValueList[0] = self._CurrentLine\r
+\r
+    ## [LibraryClasses] section\r
+    @ParseMacro\r
+    def _LibraryClassParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
+        if len(TokenList) < 2:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",\r
+                            ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if TokenList[0] == '':\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",\r
+                            ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if TokenList[1] == '':\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",\r
+                            ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+        self._ValueList[0:len(TokenList)] = TokenList\r
+\r
+    def _CompponentSourceOverridePathParser(self):\r
+        self._ValueList[0] = self._CurrentLine\r
+\r
+    ## [BuildOptions] section parser\r
+    @ParseMacro\r
+    def _BuildOptionParser(self):\r
+        self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
+        TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
+        if len(TokenList2) == 2:\r
+            self._ValueList[0] = TokenList2[0]  # toolchain family\r
+            self._ValueList[1] = TokenList2[1]  # keys\r
+        else:\r
+            self._ValueList[1] = TokenList[0]\r
+        if len(TokenList) == 2:                 # value\r
+            self._ValueList[2] = TokenList[1]\r
+\r
+        if self._ValueList[1].count('_') != 4:\r
+            EdkLogger.error(\r
+                'Parser',\r
+                FORMAT_INVALID,\r
+                "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
+                ExtraData=self._CurrentLine,\r
+                File=self.MetaFile,\r
+                Line=self._LineIndex + 1\r
+                )\r
+\r
+    ## Override parent's method since we'll do all macro replacements in parser\r
+    def _GetMacros(self):\r
+        Macros = {}\r
+        Macros.update(self._FileLocalMacros)\r
+        Macros.update(self._GetApplicableSectionMacro())\r
+        Macros.update(GlobalData.gEdkGlobal)\r
+        Macros.update(GlobalData.gPlatformDefines)\r
+        Macros.update(GlobalData.gCommandLineDefines)\r
+        # PCD cannot be referenced in macro definition\r
+        if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:\r
+            Macros.update(self._Symbols)\r
+        if GlobalData.BuildOptionPcd:\r
+            for Item in GlobalData.BuildOptionPcd:\r
+                if isinstance(Item, tuple):\r
+                    continue\r
+                PcdName, TmpValue = Item.split("=")\r
+                TmpValue = BuildOptionValue(TmpValue, self._GuidDict)\r
+                Macros[PcdName.strip()] = TmpValue\r
+        return Macros\r
+\r
+    def _PostProcess(self):\r
+        Processer = {\r
+            MODEL_META_DATA_SECTION_HEADER                  :   self.__ProcessSectionHeader,\r
+            MODEL_META_DATA_SUBSECTION_HEADER               :   self.__ProcessSubsectionHeader,\r
+            MODEL_META_DATA_HEADER                          :   self.__ProcessDefine,\r
+            MODEL_META_DATA_DEFINE                          :   self.__ProcessDefine,\r
+            MODEL_META_DATA_GLOBAL_DEFINE                   :   self.__ProcessDefine,\r
+            MODEL_META_DATA_INCLUDE                         :   self.__ProcessDirective,\r
+            MODEL_META_DATA_CONDITIONAL_STATEMENT_IF        :   self.__ProcessDirective,\r
+            MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE      :   self.__ProcessDirective,\r
+            MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF     :   self.__ProcessDirective,\r
+            MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF    :   self.__ProcessDirective,\r
+            MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF     :   self.__ProcessDirective,\r
+            MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF    :   self.__ProcessDirective,\r
+            MODEL_EFI_SKU_ID                                :   self.__ProcessSkuId,\r
+            MODEL_EFI_DEFAULT_STORES                        :   self.__ProcessDefaultStores,\r
+            MODEL_EFI_LIBRARY_INSTANCE                      :   self.__ProcessLibraryInstance,\r
+            MODEL_EFI_LIBRARY_CLASS                         :   self.__ProcessLibraryClass,\r
+            MODEL_PCD_FIXED_AT_BUILD                        :   self.__ProcessPcd,\r
+            MODEL_PCD_PATCHABLE_IN_MODULE                   :   self.__ProcessPcd,\r
+            MODEL_PCD_FEATURE_FLAG                          :   self.__ProcessPcd,\r
+            MODEL_PCD_DYNAMIC_DEFAULT                       :   self.__ProcessPcd,\r
+            MODEL_PCD_DYNAMIC_HII                           :   self.__ProcessPcd,\r
+            MODEL_PCD_DYNAMIC_VPD                           :   self.__ProcessPcd,\r
+            MODEL_PCD_DYNAMIC_EX_DEFAULT                    :   self.__ProcessPcd,\r
+            MODEL_PCD_DYNAMIC_EX_HII                        :   self.__ProcessPcd,\r
+            MODEL_PCD_DYNAMIC_EX_VPD                        :   self.__ProcessPcd,\r
+            MODEL_META_DATA_COMPONENT                       :   self.__ProcessComponent,\r
+            MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH  :   self.__ProcessSourceOverridePath,\r
+            MODEL_META_DATA_BUILD_OPTION                    :   self.__ProcessBuildOption,\r
+            MODEL_UNKNOWN                                   :   self._Skip,\r
+            MODEL_META_DATA_USER_EXTENSION                  :   self._SkipUserExtension,\r
+            MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR     :   self._ProcessError,\r
+        }\r
+\r
+        self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)\r
+        self._Table.Create()\r
+        self._DirectiveStack = []\r
+        self._DirectiveEvalStack = []\r
+        self._FileWithError = self.MetaFile\r
+        self._FileLocalMacros = {}\r
+        self._SectionsMacroDict.clear()\r
+        GlobalData.gPlatformDefines = {}\r
+\r
+        # Get all macro and PCD which has straitforward value\r
+        self.__RetrievePcdValue()\r
+        self._Content = self._RawTable.GetAll()\r
+        self._ContentIndex = 0\r
+        self._InSubsection = False\r
+        while self._ContentIndex < len(self._Content) :\r
+            Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \\r
+                LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]\r
+\r
+            if self._From < 0:\r
+                self._FileWithError = self.MetaFile\r
+\r
+            self._ContentIndex += 1\r
+\r
+            self._Scope = [[S1, S2, S3]]\r
+            #\r
+            # For !include directive, handle it specially,\r
+            # merge arch and module type in case of duplicate items\r
+            #\r
+            while self._ItemType == MODEL_META_DATA_INCLUDE:\r
+                if self._ContentIndex >= len(self._Content):\r
+                    break\r
+                Record = self._Content[self._ContentIndex]\r
+                if LineStart == Record[10] and LineEnd == Record[12]:\r
+                    if [Record[5], Record[6], Record[7]] not in self._Scope:\r
+                        self._Scope.append([Record[5], Record[6], Record[7]])\r
+                    self._ContentIndex += 1\r
+                else:\r
+                    break\r
+\r
+            self._LineIndex = LineStart - 1\r
+            self._ValueList = [V1, V2, V3]\r
+\r
+            if Owner > 0 and Owner in self._IdMapping:\r
+                self._InSubsection = True\r
+            else:\r
+                self._InSubsection = False\r
+            try:\r
+                Processer[self._ItemType]()\r
+            except EvaluationException as Excpt:\r
+                #\r
+                # Only catch expression evaluation error here. We need to report\r
+                # the precise number of line on which the error occurred\r
+                #\r
+                if hasattr(Excpt, 'Pcd'):\r
+                    if Excpt.Pcd in GlobalData.gPlatformOtherPcds:\r
+                        Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]\r
+                        EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"\r
+                                        " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"\r
+                                        " of the DSC file, and it is currently defined in this section:"\r
+                                        " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),\r
+                                    File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
+                                    Line=self._LineIndex + 1)\r
+                    else:\r
+                        EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,\r
+                                    File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
+                                    Line=self._LineIndex + 1)\r
+                else:\r
+                    EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
+                                    File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
+                                    Line=self._LineIndex + 1)\r
+            except MacroException as Excpt:\r
+                EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),\r
+                                File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
+                                Line=self._LineIndex + 1)\r
+\r
+            if self._ValueList is None:\r
+                continue\r
+\r
+            NewOwner = self._IdMapping.get(Owner, -1)\r
+            self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))\r
+            self._LastItem = self._Store(\r
+                                self._ItemType,\r
+                                self._ValueList[0],\r
+                                self._ValueList[1],\r
+                                self._ValueList[2],\r
+                                S1,\r
+                                S2,\r
+                                S3,\r
+                                NewOwner,\r
+                                self._From,\r
+                                self._LineIndex + 1,\r
+                                - 1,\r
+                                self._LineIndex + 1,\r
+                                - 1,\r
+                                self._Enabled\r
+                                )\r
+            self._IdMapping[Id] = self._LastItem\r
+\r
+        GlobalData.gPlatformDefines.update(self._FileLocalMacros)\r
+        self._PostProcessed = True\r
+        self._Content = None\r
+    def _ProcessError(self):\r
+        if not self._Enabled:\r
+            return\r
+        EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+    def __ProcessSectionHeader(self):\r
+        self._SectionName = self._ValueList[0]\r
+        if self._SectionName in self.DataType:\r
+            self._SectionType = self.DataType[self._SectionName]\r
+        else:\r
+            self._SectionType = MODEL_UNKNOWN\r
+\r
+    def __ProcessSubsectionHeader(self):\r
+        self._SubsectionName = self._ValueList[0]\r
+        if self._SubsectionName in self.DataType:\r
+            self._SubsectionType = self.DataType[self._SubsectionName]\r
+        else:\r
+            self._SubsectionType = MODEL_UNKNOWN\r
+\r
+    def __RetrievePcdValue(self):\r
+        Content = open(str(self.MetaFile), 'r').readlines()\r
+        GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)\r
+        for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,\r
+                        MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,\r
+                        MODEL_PCD_DYNAMIC_EX_VPD):\r
+            Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)\r
+            for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:\r
+                Name = TokenSpaceGuid + '.' + PcdName\r
+                if Name not in GlobalData.gPlatformOtherPcds:\r
+                    PcdLine = Line\r
+                    while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):\r
+                        Line -= 1\r
+                    GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)\r
+\r
+    def __ProcessDefine(self):\r
+        if not self._Enabled:\r
+            return\r
+\r
+        Type, Name, Value = self._ValueList\r
+        Value = ReplaceMacro(Value, self._Macros, False)\r
+        #\r
+        # If it is <Defines>, return\r
+        #\r
+        if self._InSubsection:\r
+            self._ValueList = [Type, Name, Value]\r
+            return\r
+\r
+        if self._ItemType == MODEL_META_DATA_DEFINE:\r
+            if self._SectionType == MODEL_META_DATA_HEADER:\r
+                self._FileLocalMacros[Name] = Value\r
+            else:\r
+                self._ConstructSectionMacroDict(Name, Value)\r
+        elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:\r
+            GlobalData.gEdkGlobal[Name] = Value\r
+\r
+        #\r
+        # Keyword in [Defines] section can be used as Macros\r
+        #\r
+        if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):\r
+            self._FileLocalMacros[Name] = Value\r
+\r
+        self._ValueList = [Type, Name, Value]\r
+\r
+    def __ProcessDirective(self):\r
+        Result = None\r
+        if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
+                              MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:\r
+            Macros = self._Macros\r
+            Macros.update(GlobalData.gGlobalDefines)\r
+            try:\r
+                Result = ValueExpression(self._ValueList[1], Macros)()\r
+            except SymbolNotFound as Exc:\r
+                EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
+                Result = False\r
+            except WrnExpression as Excpt:\r
+                #\r
+                # Catch expression evaluation warning here. We need to report\r
+                # the precise number of line and return the evaluation result\r
+                #\r
+                EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),\r
+                                File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
+                                Line=self._LineIndex + 1)\r
+                Result = Excpt.result\r
+\r
+        if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
+                              MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
+                              MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
+            self._DirectiveStack.append(self._ItemType)\r
+            if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:\r
+                Result = bool(Result)\r
+            else:\r
+                Macro = self._ValueList[1]\r
+                Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro\r
+                Result = Macro in self._Macros\r
+                if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:\r
+                    Result = not Result\r
+            self._DirectiveEvalStack.append(Result)\r
+        elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:\r
+            self._DirectiveStack.append(self._ItemType)\r
+            self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
+            self._DirectiveEvalStack.append(bool(Result))\r
+        elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
+            self._DirectiveStack.append(self._ItemType)\r
+            self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
+            self._DirectiveEvalStack.append(True)\r
+        elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
+            # Back to the nearest !if/!ifdef/!ifndef\r
+            while self._DirectiveStack:\r
+                self._DirectiveEvalStack.pop()\r
+                Directive = self._DirectiveStack.pop()\r
+                if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
+                                 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
+                                 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
+                    break\r
+        elif self._ItemType == MODEL_META_DATA_INCLUDE:\r
+            # The included file must be relative to workspace or same directory as DSC file\r
+            __IncludeMacros = {}\r
+            #\r
+            # Allow using system environment variables  in path after !include\r
+            #\r
+            __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']\r
+            if "ECP_SOURCE" in GlobalData.gGlobalDefines:\r
+                __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']\r
+            #\r
+            # During GenFds phase call DSC parser, will go into this branch.\r
+            #\r
+            elif "ECP_SOURCE" in GlobalData.gCommandLineDefines:\r
+                __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']\r
+\r
+            __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']\r
+            __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']\r
+            #\r
+            # Allow using MACROs comes from [Defines] section to keep compatible.\r
+            #\r
+            __IncludeMacros.update(self._Macros)\r
+\r
+            IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))\r
+            #\r
+            # First search the include file under the same directory as DSC file\r
+            #\r
+            IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)\r
+            ErrorCode, ErrorInfo1 = IncludedFile1.Validate()\r
+            if ErrorCode != 0:\r
+                #\r
+                # Also search file under the WORKSPACE directory\r
+                #\r
+                IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)\r
+                ErrorCode, ErrorInfo2 = IncludedFile1.Validate()\r
+                if ErrorCode != 0:\r
+                    EdkLogger.error('parser', ErrorCode, File=self._FileWithError,\r
+                                    Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)\r
+\r
+            self._FileWithError = IncludedFile1\r
+\r
+            FromItem = self._Content[self._ContentIndex - 1][0]\r
+            if self._InSubsection:\r
+                Owner = self._Content[self._ContentIndex - 1][8]\r
+            else:\r
+                Owner = self._Content[self._ContentIndex - 1][0]\r
+            IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)\r
+            Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,\r
+                               Owner=Owner, From=FromItem)\r
+\r
+            self.IncludedFiles.add (IncludedFile1)\r
+\r
+            # set the parser status with current status\r
+            Parser._SectionName = self._SectionName\r
+            Parser._SubsectionType = self._SubsectionType\r
+            Parser._InSubsection = self._InSubsection\r
+            Parser._SectionType = self._SectionType\r
+            Parser._Scope = self._Scope\r
+            Parser._Enabled = self._Enabled\r
+            # Parse the included file\r
+            Parser.Start()\r
+\r
+\r
+            # Insert all records in the table for the included file into dsc file table\r
+            Records = IncludedFileTable.GetAll()\r
+            if Records:\r
+                self._Content[self._ContentIndex:self._ContentIndex] = Records\r
+                self._Content.pop(self._ContentIndex - 1)\r
+                self._ValueList = None\r
+                self._ContentIndex -= 1\r
+\r
+    def __ProcessSkuId(self):\r
+        self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
+                           for Value in self._ValueList]\r
+    def __ProcessDefaultStores(self):\r
+        self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
+                           for Value in self._ValueList]\r
+\r
+    def __ProcessLibraryInstance(self):\r
+        self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
+\r
+    def __ProcessLibraryClass(self):\r
+        self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)\r
+\r
+    def __ProcessPcd(self):\r
+        if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:\r
+            self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)\r
+            return\r
+\r
+        ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)\r
+        if not Valid:\r
+            EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,\r
+                            ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
+        PcdValue = ValList[Index]\r
+        if PcdValue and "." not in self._ValueList[0]:\r
+            try:\r
+                ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)\r
+            except WrnExpression as Value:\r
+                ValList[Index] = Value.result\r
+            except:\r
+                pass\r
+\r
+        if ValList[Index] == 'True':\r
+            ValList[Index] = '1'\r
+        if ValList[Index] == 'False':\r
+            ValList[Index] = '0'\r
+\r
+        if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):\r
+            GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
+            self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
+        try:\r
+            self._ValueList[2] = '|'.join(ValList)\r
+        except Exception:\r
+            print(ValList)\r
+\r
+    def __ProcessComponent(self):\r
+        self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
+\r
+    def __ProcessSourceOverridePath(self):\r
+        self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
+\r
+    def __ProcessBuildOption(self):\r
+        self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)\r
+                           for Value in self._ValueList]\r
+\r
+    _SectionParser = {\r
+        MODEL_META_DATA_HEADER                          :   _DefineParser,\r
+        MODEL_EFI_SKU_ID                                :   _SkuIdParser,\r
+        MODEL_EFI_DEFAULT_STORES                        :   _DefaultStoresParser,\r
+        MODEL_EFI_LIBRARY_INSTANCE                      :   _LibraryInstanceParser,\r
+        MODEL_EFI_LIBRARY_CLASS                         :   _LibraryClassParser,\r
+        MODEL_PCD_FIXED_AT_BUILD                        :   _PcdParser,\r
+        MODEL_PCD_PATCHABLE_IN_MODULE                   :   _PcdParser,\r
+        MODEL_PCD_FEATURE_FLAG                          :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC_DEFAULT                       :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC_HII                           :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC_VPD                           :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC_EX_DEFAULT                    :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC_EX_HII                        :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC_EX_VPD                        :   _PcdParser,\r
+        MODEL_META_DATA_COMPONENT                       :   _ComponentParser,\r
+        MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH  :   _CompponentSourceOverridePathParser,\r
+        MODEL_META_DATA_BUILD_OPTION                    :   _BuildOptionParser,\r
+        MODEL_UNKNOWN                                   :   MetaFileParser._Skip,\r
+        MODEL_META_DATA_USER_EXTENSION                  :   MetaFileParser._SkipUserExtension,\r
+        MODEL_META_DATA_SECTION_HEADER                  :   MetaFileParser._SectionHeaderParser,\r
+        MODEL_META_DATA_SUBSECTION_HEADER               :   _SubsectionHeaderParser,\r
+    }\r
+\r
+    _Macros = property(_GetMacros)\r
+\r
+## DEC file parser class\r
+#\r
+#   @param      FilePath        The path of platform description file\r
+#   @param      FileType        The raw data of DSC file\r
+#   @param      Table           Database used to retrieve module/package information\r
+#   @param      Macros          Macros used for replacement in file\r
+#\r
+class DecParser(MetaFileParser):\r
+    # DEC file supported data types (one type per section)\r
+    DataType = {\r
+        TAB_DEC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,\r
+        TAB_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,\r
+        TAB_INCLUDES.upper()                        :   MODEL_EFI_INCLUDE,\r
+        TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,\r
+        TAB_GUIDS.upper()                           :   MODEL_EFI_GUID,\r
+        TAB_PPIS.upper()                            :   MODEL_EFI_PPI,\r
+        TAB_PROTOCOLS.upper()                       :   MODEL_EFI_PROTOCOL,\r
+        TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,\r
+        TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,\r
+        TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,\r
+        TAB_PCDS_DYNAMIC_NULL.upper()               :   MODEL_PCD_DYNAMIC,\r
+        TAB_PCDS_DYNAMIC_EX_NULL.upper()            :   MODEL_PCD_DYNAMIC_EX,\r
+        TAB_USER_EXTENSIONS.upper()                 :   MODEL_META_DATA_USER_EXTENSION,\r
+    }\r
+\r
+    ## Constructor of DecParser\r
+    #\r
+    #  Initialize object of DecParser\r
+    #\r
+    #   @param      FilePath        The path of platform description file\r
+    #   @param      FileType        The raw data of DSC file\r
+    #   @param      Arch            Default Arch value for filtering sections\r
+    #   @param      Table           Database used to retrieve module/package information\r
+    #\r
+    def __init__(self, FilePath, FileType, Arch, Table):\r
+        # prevent re-initialization\r
+        if hasattr(self, "_Table"):\r
+            return\r
+        MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)\r
+        self._Comments = []\r
+        self._Version = 0x00010005  # Only EDK2 dec file is supported\r
+        self._AllPCDs = [] # Only for check duplicate PCD\r
+        self._AllPcdDict = {}\r
+\r
+        self._CurrentStructurePcdName = ""\r
+        self._include_flag = False\r
+        self._package_flag = False\r
+\r
+    ## Parser starter\r
+    def Start(self):\r
+        Content = ''\r
+        try:\r
+            Content = open(str(self.MetaFile), 'r').readlines()\r
+        except:\r
+            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
+\r
+        self._DefinesCount = 0\r
+        for Index in range(0, len(Content)):\r
+            Line, Comment = CleanString2(Content[Index])\r
+            self._CurrentLine = Line\r
+            self._LineIndex = Index\r
+\r
+            # save comment for later use\r
+            if Comment:\r
+                self._Comments.append((Comment, self._LineIndex + 1))\r
+            # skip empty line\r
+            if Line == '':\r
+                continue\r
+\r
+            # section header\r
+            if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
+                self._SectionHeaderParser()\r
+                if self._SectionName == TAB_DEC_DEFINES.upper():\r
+                    self._DefinesCount += 1\r
+                self._Comments = []\r
+                continue\r
+            if self._SectionType == MODEL_UNKNOWN:\r
+                EdkLogger.error("Parser", FORMAT_INVALID,\r
+                                ""\r
+                                "Not able to determine \"%s\" in which section."%self._CurrentLine,\r
+                                self.MetaFile, self._LineIndex + 1)\r
+            elif len(self._SectionType) == 0:\r
+                self._Comments = []\r
+                continue\r
+\r
+            # section content\r
+            self._ValueList = ['', '', '']\r
+            self._SectionParser[self._SectionType[0]](self)\r
+            if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
+                self._ItemType = -1\r
+                self._Comments = []\r
+                continue\r
+\r
+            #\r
+            # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,\r
+            # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1\r
+            #\r
+            for Arch, ModuleType, Type in self._Scope:\r
+                self._LastItem = self._Store(\r
+                    Type,\r
+                    self._ValueList[0],\r
+                    self._ValueList[1],\r
+                    self._ValueList[2],\r
+                    Arch,\r
+                    ModuleType,\r
+                    self._Owner[-1],\r
+                    self._LineIndex + 1,\r
+                    - 1,\r
+                    self._LineIndex + 1,\r
+                    - 1,\r
+                    0\r
+                    )\r
+                for Comment, LineNo in self._Comments:\r
+                    self._Store(\r
+                        MODEL_META_DATA_COMMENT,\r
+                        Comment,\r
+                        self._ValueList[0],\r
+                        self._ValueList[1],\r
+                        Arch,\r
+                        ModuleType,\r
+                        self._LastItem,\r
+                        LineNo,\r
+                        - 1,\r
+                        LineNo,\r
+                        - 1,\r
+                        0\r
+                        )\r
+            self._Comments = []\r
+        if self._DefinesCount > 1:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )\r
+        if self._DefinesCount == 0:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)\r
+        self._Done()\r
+\r
+\r
+    ## Section header parser\r
+    #\r
+    #   The section header is always in following format:\r
+    #\r
+    #       [section_name.arch<.platform|module_type>]\r
+    #\r
+    def _SectionHeaderParser(self):\r
+        self._Scope = []\r
+        self._SectionName = ''\r
+        self._SectionType = []\r
+        ArchList = set()\r
+        PrivateList = set()\r
+        Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)\r
+        for Item in Line[1:-1].split(TAB_COMMA_SPLIT):\r
+            if Item == '':\r
+                EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,\r
+                                "section name can NOT be empty or incorrectly use separator comma",\r
+                                self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
+            ItemList = Item.split(TAB_SPLIT)\r
+\r
+            # different types of PCD are permissible in one section\r
+            self._SectionName = ItemList[0].upper()\r
+            if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):\r
+                EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",\r
+                                self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
+            if self._SectionName in self.DataType:\r
+                if self.DataType[self._SectionName] not in self._SectionType:\r
+                    self._SectionType.append(self.DataType[self._SectionName])\r
+            else:\r
+                EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
+                                self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
+\r
+            if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:\r
+                EdkLogger.error(\r
+                            'Parser',\r
+                            FORMAT_INVALID,\r
+                            "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,\r
+                            File=self.MetaFile,\r
+                            Line=self._LineIndex + 1,\r
+                            ExtraData=self._CurrentLine\r
+                            )\r
+            # S1 is always Arch\r
+            if len(ItemList) > 1:\r
+                S1 = ItemList[1].upper()\r
+            else:\r
+                S1 = TAB_ARCH_COMMON\r
+            ArchList.add(S1)\r
+            # S2 may be Platform or ModuleType\r
+            if len(ItemList) > 2:\r
+                S2 = ItemList[2].upper()\r
+                # only Includes, GUIDs, PPIs, Protocols section have Private tag\r
+                if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:\r
+                    if S2 != 'PRIVATE':\r
+                        EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',\r
+                                        File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
+            else:\r
+                S2 = TAB_COMMON\r
+            PrivateList.add(S2)\r
+            if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
+                self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
+\r
+        # 'COMMON' must not be used with specific ARCHs at the same section\r
+        if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
+\r
+        # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute\r
+        if TAB_COMMON in PrivateList and len(PrivateList) > 1:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
+\r
+    ## [guids], [ppis] and [protocols] section parser\r
+    @ParseMacro\r
+    def _GuidParser(self):\r
+        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
+        if len(TokenList) < 2:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",\r
+                            ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if TokenList[0] == '':\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",\r
+                            ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if TokenList[1] == '':\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",\r
+                            ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
+                            ExtraData=self._CurrentLine + \\r
+                                      " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
+                            File=self.MetaFile, Line=self._LineIndex + 1)\r
+        self._ValueList[0] = TokenList[0]\r
+        self._ValueList[1] = TokenList[1]\r
+        if self._ValueList[0] not in self._GuidDict:\r
+            self._GuidDict[self._ValueList[0]] = self._ValueList[1]\r
+\r
+    ## PCD sections parser\r
+    #\r
+    #   [PcdsFixedAtBuild]\r
+    #   [PcdsPatchableInModule]\r
+    #   [PcdsFeatureFlag]\r
+    #   [PcdsDynamicEx\r
+    #   [PcdsDynamic]\r
+    #\r
+    @ParseMacro\r
+    def _PcdParser(self):\r
+        if self._CurrentStructurePcdName:\r
+            self._ValueList[0] = self._CurrentStructurePcdName\r
+\r
+            if "|" not in self._CurrentLine:\r
+                if "<HeaderFiles>" == self._CurrentLine:\r
+                    self._include_flag = True\r
+                    self._package_flag = False\r
+                    self._ValueList = None\r
+                    return\r
+                if "<Packages>" == self._CurrentLine:\r
+                    self._package_flag = True\r
+                    self._ValueList = None\r
+                    self._include_flag = False\r
+                    return\r
+\r
+                if self._include_flag:\r
+                    self._ValueList[1] = "<HeaderFiles>_" + md5.new(self._CurrentLine).hexdigest()\r
+                    self._ValueList[2] = self._CurrentLine\r
+                if self._package_flag and "}" != self._CurrentLine:\r
+                    self._ValueList[1] = "<Packages>_" + md5.new(self._CurrentLine).hexdigest()\r
+                    self._ValueList[2] = self._CurrentLine\r
+                if self._CurrentLine == "}":\r
+                    self._package_flag = False\r
+                    self._include_flag = False\r
+                    self._ValueList = None\r
+                    return\r
+            else:\r
+                PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)\r
+                PcdNames = PcdTockens[0].split(TAB_SPLIT)\r
+                if len(PcdNames) == 2:\r
+                    self._CurrentStructurePcdName = ""\r
+                else:\r
+                    if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):\r
+                        EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+                    self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])\r
+                    self._ValueList[2] = PcdTockens[1]\r
+        if not self._CurrentStructurePcdName:\r
+            TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
+            self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
+            ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')\r
+            # check PCD information\r
+            if self._ValueList[0] == '' or self._ValueList[1] == '':\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
+                                ExtraData=self._CurrentLine + \\r
+                                          " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+            # check format of token space GUID CName\r
+            if not ValueRe.match(self._ValueList[0]):\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",\r
+                                ExtraData=self._CurrentLine + \\r
+                                          " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+            # check format of PCD CName\r
+            if not ValueRe.match(self._ValueList[1]):\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",\r
+                                ExtraData=self._CurrentLine + \\r
+                                          " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+            # check PCD datum information\r
+            if len(TokenList) < 2 or TokenList[1] == '':\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
+                                ExtraData=self._CurrentLine + \\r
+                                          " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+\r
+            ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
+            PtrValue = ValueRe.findall(TokenList[1])\r
+\r
+            # Has VOID* type string, may contain "|" character in the string.\r
+            if len(PtrValue) != 0:\r
+                ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
+                ValueList = AnalyzePcdExpression(ptrValueList)\r
+                ValueList[0] = PtrValue[0]\r
+            else:\r
+                ValueList = AnalyzePcdExpression(TokenList[1])\r
+\r
+\r
+            # check if there's enough datum information given\r
+            if len(ValueList) != 3:\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",\r
+                                ExtraData=self._CurrentLine + \\r
+                                          " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+            # check default value\r
+            if ValueList[0] == '':\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",\r
+                                ExtraData=self._CurrentLine + \\r
+                                          " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+            # check datum type\r
+            if ValueList[1] == '':\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",\r
+                                ExtraData=self._CurrentLine + \\r
+                                          " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+            # check token of the PCD\r
+            if ValueList[2] == '':\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",\r
+                                ExtraData=self._CurrentLine + \\r
+                                          " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+            PcdValue = ValueList[0]\r
+            if PcdValue:\r
+                try:\r
+                    self._GuidDict.update(self._AllPcdDict)\r
+                    ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)\r
+                except BadExpression as Value:\r
+                    EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+            # check format of default value against the datum type\r
+            IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
+            if not IsValid:\r
+                EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,\r
+                                File=self.MetaFile, Line=self._LineIndex + 1)\r
+\r
+            if Cause == "StructurePcd":\r
+                self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])\r
+                self._ValueList[0] = self._CurrentStructurePcdName\r
+                self._ValueList[1] = ValueList[1].strip()\r
+\r
+            if ValueList[0] in ['True', 'true', 'TRUE']:\r
+                ValueList[0] = '1'\r
+            elif ValueList[0] in ['False', 'false', 'FALSE']:\r
+                ValueList[0] = '0'\r
+\r
+            # check for duplicate PCD definition\r
+            if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:\r
+                EdkLogger.error('Parser', FORMAT_INVALID,\r
+                                "The same PCD name and GUID have been already defined",\r
+                                ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
+            else:\r
+                self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))\r
+                self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]\r
+\r
+            self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
+\r
+    _SectionParser = {\r
+        MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,\r
+        MODEL_EFI_INCLUDE               :   MetaFileParser._PathParser,\r
+        MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,\r
+        MODEL_EFI_GUID                  :   _GuidParser,\r
+        MODEL_EFI_PPI                   :   _GuidParser,\r
+        MODEL_EFI_PROTOCOL              :   _GuidParser,\r
+        MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,\r
+        MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,\r
+        MODEL_PCD_FEATURE_FLAG          :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC               :   _PcdParser,\r
+        MODEL_PCD_DYNAMIC_EX            :   _PcdParser,\r
+        MODEL_UNKNOWN                   :   MetaFileParser._Skip,\r
+        MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._SkipUserExtension,\r
+    }\r
+\r
+##\r
+#\r
+# This acts like the main() function for the script, unless it is 'import'ed into another\r
+# script.\r
+#\r
+if __name__ == '__main__':\r
+    pass\r
+\r