]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py
BaseTools: cleanup class heirarchy
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / MetaFileWorkspace / MetaFileParser.py
index d10265e973c4f2f35f34206ef3e78c31138e6762..237cf5acfea13ad0210cf3edda189e1b8d2fbe9f 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 re
-import time
-import copy
-
-import Common.EdkLogger as EdkLogger
-import Common.GlobalData as GlobalData
-import EccGlobalData
-
-from CommonDataClass.DataClass import *
-from Common.DataType import *
-from Common.String import *
-from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData
-from Common.Expression import *
-from CommonDataClass.Exceptions import *
-
-from MetaFileTable import MetaFileStorage
-from GenFds.FdfParser import FdfParser  
-
-## A decorator used to parse macro definition
-def ParseMacro(Parser):
-    def MacroParser(self):
-        Match = gMacroDefPattern.match(self._CurrentLine)
-        if not Match:
-            # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
-            Parser(self)
-            return
-
-        TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)
-        # Syntax check
-        if not TokenList[0]:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        if len(TokenList) < 2:
-            TokenList.append('')
-
-        Type = Match.group(1)
-        Name, Value = TokenList
-        # Global macros can be only defined via environment variable
-        if Name in GlobalData.gGlobalDefines:
-            EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        # Only upper case letters, digit and '_' are allowed
-        if not gMacroNamePattern.match(Name):
-            EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-
-        Value = ReplaceMacro(Value, self._Macros)
-        self._ItemType = MODEL_META_DATA_DEFINE
-        # DEFINE defined macros
-        if Type == TAB_DSC_DEFINES_DEFINE:
-            if type(self) == DecParser:
-                if MODEL_META_DATA_HEADER in self._SectionType:
-                    self._FileLocalMacros[Name] = Value
-                else:
-                    for Scope in self._Scope:
-                        self._SectionsMacroDict.setdefault((Scope[2], Scope[0], Scope[1]), {})[Name] = Value
-            elif self._SectionType == MODEL_META_DATA_HEADER:
-                self._FileLocalMacros[Name] = Value
-            else:
-                SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
-                if SectionDictKey not in self._SectionsMacroDict:
-                    self._SectionsMacroDict[SectionDictKey] = {}
-                SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
-                SectionLocalMacros[Name] = Value
-        # EDK_GLOBAL defined macros
-        elif type(self) != DscParser:
-            EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        elif self._SectionType != MODEL_META_DATA_HEADER:
-            EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
-            EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-            
-        self._ValueList = [Type, Name, Value]
-
-    return MacroParser
-
-## 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, Owner=-1, From=-1):
-        self._Table = Table
-        self._RawTable = Table
-        self._FileType = FileType
-        self.MetaFile = FilePath
-        self._Defines = {}
-        self._FileLocalMacros = {}
-        self._SectionsMacroDict = {}
-
-        # for recursive parsing
-        self._Owner = [Owner]
-        self._From = From
-
-        # parsr status for parsing
-        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._ItemType = MODEL_UNKNOWN
-        self._LastItem = -1
-        self._Enabled = 0
-        self._Finished = False
-        self._PostProcessed = False
-        # Different version of meta-file has different way to parse.
-        self._Version = 0
-
-    ## 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
-
-    ## Notify a post-process is needed
-    def DoPostProcess(self):
-        self._PostProcessed = False
-
-    ## 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()
-
-    def _PostProcess(self):
-        self._PostProcessed = True
-
-    ## 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,)
-
-        # Parse the file first, if necessary
-        if not self._Finished:
-            if self._RawTable.IsIntegrity():
-                self._Finished = True
-            else:
-                self._Table = self._RawTable
-                self._PostProcessed = False
-                self.Start()
-
-        # No specific ARCH or Platform given, use raw data
-        if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] == None):
-            return self._RawTable.Query(*DataInfo)
-
-        # Do post-process if necessary
-        if not self._PostProcessed:
-            self._PostProcess()
-
-        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
-    #
-    @ParseMacro
-    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.
-    #
-    @ParseMacro
-    def _PathParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
-        self._ValueList[0:len(TokenList)] = TokenList
-        # Don't do macro replacement for dsc file at this point
-        if type(self) != DscParser:
-            Macros = self._Macros
-            self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
-
-    ## 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)
-        # If the section information is needed later, it should be stored in database
-        self._ValueList[0] = self._SectionName
-
-    ## [defines] section parser
-    @ParseMacro
-    def _DefineParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
-        self._ValueList[1:len(TokenList)] = TokenList
-        if not self._ValueList[1]:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        if not self._ValueList[2]:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-
-        self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
-        Name, Value = self._ValueList[1], self._ValueList[2]
-        # Sometimes, we need to make differences between EDK and EDK2 modules 
-        if Name == 'INF_VERSION':
-            try:
-                self._Version = int(Value, 0)
-            except:
-                EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
-                                ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-
-        if type(self) == InfParser and self._Version < 0x00010005:
-            # EDK module allows using defines as macros
-            self._FileLocalMacros[Name] = Value
-        self._Defines[Name] = Value
-
-    ## [BuildOptions] section parser
-    @ParseMacro
-    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 and type(self) != DscParser: # 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
-                )
-
-    def _GetMacros(self):
-        Macros = {}
-        Macros.update(self._FileLocalMacros)
-        Macros.update(self._GetApplicableSectionMacro())
-        return Macros
-
-
-    ## Get section Macros that are applicable to current line, which may come from other sections 
-    ## that share the same name while scope is wider
-    def _GetApplicableSectionMacro(self):
-        Macros = {}
-        for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", self._Scope[0][1]),
-                               (self._Scope[0][0], "COMMON"), (self._Scope[0][0], self._Scope[0][1])]:
-            if (self._SectionType, Scope1, Scope2) in self._SectionsMacroDict:
-                Macros.update(self._SectionsMacroDict[(self._SectionType, Scope1, Scope2)])
-        return Macros
-
-    _SectionParser  = {}
-    Finished        = property(_GetFinished, _SetFinished)
-    _Macros         = property(_GetMacros)
-
-
-## 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_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
-        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):
-        # prevent re-initialization
-        if hasattr(self, "_Table"):
-            return
-        MetaFileParser.__init__(self, FilePath, FileType, Table)
-        self.TblFile = EccGlobalData.gDb.TblFile
-        self.FileID = -1
-
-    ## Parser starter
-    def Start(self):
-        NmakeLine = ''
-        Content = ''
-        try:
-            Content = open(str(self.MetaFile), 'r').readlines()
-        except:
-            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
-        #
-        # Insert a record for file
-        #
-        Filename = NormPath(self.MetaFile)
-        FileID = self.TblFile.GetFileId(Filename)
-        if FileID:
-            self.FileID = FileID
-        else:
-            self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_INF)
-            
-        # parse the file line by line
-        IsFindBlockComment = False
-
-        for Index in range(0, len(Content)):
-            # skip empty, commented, block commented lines
-            Line = CleanString(Content[Index], AllowCppStyleComment=True)
-            NextLine = ''
-            if Index + 1 < len(Content):
-                NextLine = CleanString(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()
-                # Check invalid sections
-                if self._Version < 0x00010005:
-                    if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
-                                             MODEL_EFI_LIBRARY_CLASS,
-                                             MODEL_META_DATA_PACKAGE,
-                                             MODEL_PCD_FIXED_AT_BUILD,
-                                             MODEL_PCD_PATCHABLE_IN_MODULE,
-                                             MODEL_PCD_FEATURE_FLAG,
-                                             MODEL_PCD_DYNAMIC_EX,
-                                             MODEL_PCD_DYNAMIC,
-                                             MODEL_EFI_GUID,
-                                             MODEL_EFI_PROTOCOL,
-                                             MODEL_EFI_PPI,
-                                             MODEL_META_DATA_USER_EXTENSION]:
-                        EdkLogger.error('Parser', FORMAT_INVALID,
-                                        "Section [%s] is not allowed in inf file without version" % (self._SectionName),
-                                        ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-                elif self._SectionType in [MODEL_EFI_INCLUDE,
-                                           MODEL_EFI_LIBRARY_INSTANCE,
-                                           MODEL_META_DATA_NMAKE]:
-                    EdkLogger.error('Parser', FORMAT_INVALID,
-                                    "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
-                                    ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-                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 = ''
-
-            # section content
-            self._ValueList = ['','','']
-            # parse current line, result will be put in self._ValueList
-            self._SectionParser[self._SectionType](self)
-            if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
-                self._ItemType = -1
-                continue
-            #
-            # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
-            # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
-            #
-            self._ValueList[0] = self._ValueList[0].replace('/', '\\')
-            for Arch, Platform in self._Scope:
-                self._Store(self._SectionType,
-                            self._ValueList[0],
-                            self._ValueList[1],
-                            self._ValueList[2],
-                            Arch,
-                            Platform,
-                            self._Owner[-1],
-                            self.FileID,
-                            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
-        Macros = self._Macros
-        if Macros:
-            for Index in range(0, len(self._ValueList)):
-                Value = self._ValueList[Index]
-                if not Value:
-                    continue
-
-                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
-
-                self._ValueList[Index] = ReplaceMacro(Value, Macros)
-
-    ## Parse [Sources] section
-    #
-    #   Only path can have macro used. So we need to replace them before use.
-    #
-    @ParseMacro
-    def _SourceFileParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
-        self._ValueList[0:len(TokenList)] = TokenList
-        Macros = self._Macros
-        # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
-        if 'COMPONENT_TYPE' in Macros:
-            if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
-                self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
-        if self._Defines['BASE_NAME'] == 'Microcode':
-            pass
-        self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
-
-    ## Parse [Binaries] section
-    #
-    #   Only path can have macro used. So we need to replace them before use.
-    #
-    @ParseMacro
-    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] = ReplaceMacro(self._ValueList[1], self._Macros)
-
-    ## [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)
-        # remove self-reference in macro setting
-        #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
-
-    ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
-    @ParseMacro
-    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
-    @ParseMacro
-    def _DepexParser(self):
-        self._ValueList[0:1] = [self._CurrentLine]
-
-    _SectionParser = {
-        MODEL_UNKNOWN                   :   MetaFileParser._Skip,
-        MODEL_META_DATA_HEADER          :   MetaFileParser._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_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,
-        TAB_DSC_DEFINES_EDKGLOBAL                   :   MODEL_META_DATA_GLOBAL_DEFINE,
-        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,
-    }
-
-    # Valid names in define section
-    DefineKeywords = [
-        "DSC_SPECIFICATION",
-        "PLATFORM_NAME",
-        "PLATFORM_GUID",
-        "PLATFORM_VERSION",
-        "SKUID_IDENTIFIER",
-        "SUPPORTED_ARCHITECTURES",
-        "BUILD_TARGETS",
-        "OUTPUT_DIRECTORY",
-        "FLASH_DEFINITION",
-        "BUILD_NUMBER",
-        "RFC_LANGUAGES",
-        "ISO_LANGUAGES",
-        "TIME_STAMP_FILE",
-        "VPD_TOOL_GUID",
-        "FIX_LOAD_TOP_MEMORY_ADDRESS"
-    ]
-
-    SymbolPattern = ValueExpression.SymbolPattern
-
-    ## 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, Owner=-1, From=-1):
-        # prevent re-initialization
-        if hasattr(self, "_Table"):
-            return
-        MetaFileParser.__init__(self, FilePath, FileType, Table, Owner, From)
-        self._Version = 0x00010005  # Only EDK2 dsc file is supported
-        # to store conditional directive evaluation result
-        self._DirectiveStack = []
-        self._DirectiveEvalStack = []
-        self._Enabled = 1
-
-        # Final valid replacable symbols
-        self._Symbols = {}
-        #
-        #  Map the ID between the original table and new table to track
-        #  the owner item
-        #
-        self._IdMapping = {-1:-1}
-        
-        self.TblFile = EccGlobalData.gDb.TblFile
-        self.FileID = -1
-
-    ## Parser starter
-    def Start(self):
-        Content = ''
-        try:
-            Content = open(str(self.MetaFile.Path), 'r').readlines()
-        except:
-            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
-        #
-        # Insert a record for file
-        #
-        Filename = NormPath(self.MetaFile.Path)
-        FileID = self.TblFile.GetFileId(Filename)
-        if FileID:
-            self.FileID = FileID
-        else:
-            self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC)
-        
-        
-        for Index in range(0, len(Content)):
-            Line = CleanString(Content[Index])
-            # skip empty line
-            if Line == '':
-                continue
-
-            self._CurrentLine = Line
-            self._LineIndex = Index
-            if self._InSubsection and self._Owner[-1] == -1:
-                self._Owner.append(self._LastItem)
-            
-            # section header
-            if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
-                self._SectionType = MODEL_META_DATA_SECTION_HEADER
-            # subsection ending
-            elif Line[0] == '}' and self._InSubsection:
-                self._InSubsection = False
-                self._SubsectionType = MODEL_UNKNOWN
-                self._SubsectionName = ''
-                self._Owner[-1] = -1
-                continue
-            # subsection header
-            elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
-                self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
-            # directive line
-            elif Line[0] == '!':
-                self._DirectiveParser()
-                continue
-
-            if self._InSubsection:
-                SectionType = self._SubsectionType
-            else:
-                SectionType = self._SectionType
-            self._ItemType = SectionType
-
-            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(
-                                        self._ItemType,
-                                        self._ValueList[0],
-                                        self._ValueList[1],
-                                        self._ValueList[2],
-                                        Arch,
-                                        ModuleType,
-                                        self._Owner[-1],
-                                        self.FileID,
-                                        self._From,
-                                        self._LineIndex+1,
-                                        -1,
-                                        self._LineIndex+1,
-                                        -1,
-                                        self._Enabled
-                                        )
-
-        if self._DirectiveStack:
-            Type, Line, Text = self._DirectiveStack[-1]
-            EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
-                            ExtraData=Text, File=self.MetaFile, Line=Line)
-        self._Done()
-
-    ## <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)
-        self._ValueList[0] = self._SubsectionName
-
-    ## Directive statement parser
-    def _DirectiveParser(self):
-        self._ValueList = ['','','']
-        TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
-        self._ValueList[0:len(TokenList)] = TokenList
-
-        # Syntax check
-        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)
-
-        ItemType = self.DataType[DirectiveName]
-        if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
-            # Remove all directives between !if and !endif, including themselves
-            while self._DirectiveStack:
-                # Remove any !else or !elseif
-                DirectiveInfo = self._DirectiveStack.pop()
-                if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
-                                        MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
-                                        MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
-                    break
-            else:
-                EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
-                                File=self.MetaFile, Line=self._LineIndex+1,
-                                ExtraData=self._CurrentLine)
-        elif ItemType != MODEL_META_DATA_INCLUDE:
-            # Break if there's a !else is followed by a !elseif
-            if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
-               self._DirectiveStack and \
-               self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
-                EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
-                                File=self.MetaFile, Line=self._LineIndex+1,
-                                ExtraData=self._CurrentLine)
-            self._DirectiveStack.append((ItemType, self._LineIndex+1, self._CurrentLine))
-        elif self._From > 0:
-            EdkLogger.error('Parser', FORMAT_INVALID,
-                            "No '!include' allowed in included file",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, 
-                            Line=self._LineIndex+1)
-
-        #
-        # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
-        # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
-        #
-        self._LastItem = self._Store(
-                                ItemType,
-                                self._ValueList[0],
-                                self._ValueList[1],
-                                self._ValueList[2],
-                                'COMMON',
-                                'COMMON',
-                                self._Owner[-1],
-                                self.FileID,
-                                self._From,
-                                self._LineIndex+1,
-                                -1,
-                                self._LineIndex+1,
-                                -1,
-                                0
-                                )
-
-    ## [defines] section parser
-    @ParseMacro
-    def _DefineParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
-        self._ValueList[1:len(TokenList)] = TokenList
-
-        # Syntax check
-        if not self._ValueList[1]:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        if not self._ValueList[2]:
-            EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        if not self._ValueList[1] in self.DefineKeywords:
-            EdkLogger.error('Parser', FORMAT_INVALID,
-                            "Unknown keyword found: %s. "
-                            "If this is a macro you must "
-                            "add it as a DEFINE in the DSC" % self._ValueList[1],
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        self._Defines[self._ValueList[1]] = self._ValueList[2]
-        self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
-
-    @ParseMacro
-    def _SkuIdParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
-        if len(TokenList) != 2:
-            EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-        self._ValueList[0:len(TokenList)] = TokenList
-
-    ## Parse Edk style of library modules
-    def _LibraryInstanceParser(self):
-        self._ValueList[0] = self._CurrentLine
-
-    ## PCD sections parser
-    #
-    #   [PcdsFixedAtBuild]
-    #   [PcdsPatchableInModule]
-    #   [PcdsFeatureFlag]
-    #   [PcdsDynamicEx
-    #   [PcdsDynamicExDefault]
-    #   [PcdsDynamicExVpd]
-    #   [PcdsDynamicExHii]
-    #   [PcdsDynamic]
-    #   [PcdsDynamicDefault]
-    #   [PcdsDynamicVpd]
-    #   [PcdsDynamicHii]
-    #
-    @ParseMacro
-    def _PcdParser(self):
-        TokenList = GetSplitValueList(self._CurrentLine, 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
-    @ParseMacro
-    def _ComponentParser(self):
-        if self._CurrentLine[-1] == '{':
-            self._ValueList[0] = self._CurrentLine[0:-1].strip()
-            self._InSubsection = True
-        else:
-            self._ValueList[0] = self._CurrentLine
-
-    ## [LibraryClasses] section
-    @ParseMacro
-    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
-
-    def _CompponentSourceOverridePathParser(self):
-        self._ValueList[0] = self._CurrentLine
-
-    ## [BuildOptions] section parser
-    @ParseMacro
-    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] = TokenList[1]
-
-        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
-                )
-
-    ## Override parent's method since we'll do all macro replacements in parser
-    def _GetMacros(self):
-        Macros = {}
-        Macros.update(self._FileLocalMacros)
-        Macros.update(self._GetApplicableSectionMacro())
-        Macros.update(GlobalData.gEdkGlobal)
-        Macros.update(GlobalData.gPlatformDefines)
-        Macros.update(GlobalData.gCommandLineDefines)
-        # PCD cannot be referenced in macro definition
-        if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
-            Macros.update(self._Symbols)
-        return Macros
-
-    def _PostProcess(self):
-        Processer = {
-            MODEL_META_DATA_SECTION_HEADER                  :   self.__ProcessSectionHeader,
-            MODEL_META_DATA_SUBSECTION_HEADER               :   self.__ProcessSubsectionHeader,
-            MODEL_META_DATA_HEADER                          :   self.__ProcessDefine,
-            MODEL_META_DATA_DEFINE                          :   self.__ProcessDefine,
-            MODEL_META_DATA_GLOBAL_DEFINE                   :   self.__ProcessDefine,
-            MODEL_META_DATA_INCLUDE                         :   self.__ProcessDirective,
-            MODEL_META_DATA_CONDITIONAL_STATEMENT_IF        :   self.__ProcessDirective,
-            MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE      :   self.__ProcessDirective,
-            MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF     :   self.__ProcessDirective,
-            MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF    :   self.__ProcessDirective,
-            MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF     :   self.__ProcessDirective,
-            MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF    :   self.__ProcessDirective,
-            MODEL_EFI_SKU_ID                                :   self.__ProcessSkuId,
-            MODEL_EFI_LIBRARY_INSTANCE                      :   self.__ProcessLibraryInstance,
-            MODEL_EFI_LIBRARY_CLASS                         :   self.__ProcessLibraryClass,
-            MODEL_PCD_FIXED_AT_BUILD                        :   self.__ProcessPcd,
-            MODEL_PCD_PATCHABLE_IN_MODULE                   :   self.__ProcessPcd,
-            MODEL_PCD_FEATURE_FLAG                          :   self.__ProcessPcd,
-            MODEL_PCD_DYNAMIC_DEFAULT                       :   self.__ProcessPcd,
-            MODEL_PCD_DYNAMIC_HII                           :   self.__ProcessPcd,
-            MODEL_PCD_DYNAMIC_VPD                           :   self.__ProcessPcd,
-            MODEL_PCD_DYNAMIC_EX_DEFAULT                    :   self.__ProcessPcd,
-            MODEL_PCD_DYNAMIC_EX_HII                        :   self.__ProcessPcd,
-            MODEL_PCD_DYNAMIC_EX_VPD                        :   self.__ProcessPcd,
-            MODEL_META_DATA_COMPONENT                       :   self.__ProcessComponent,
-            MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH  :   self.__ProcessSourceOverridePath,
-            MODEL_META_DATA_BUILD_OPTION                    :   self.__ProcessBuildOption,
-            MODEL_UNKNOWN                                   :   self._Skip,
-            MODEL_META_DATA_USER_EXTENSION                  :   self._Skip,
-        }
-        
-        self._RawTable = self._Table
-        self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)
-        self._DirectiveStack = []
-        self._DirectiveEvalStack = []
-        self._FileWithError = self.MetaFile
-        self._FileLocalMacros = {}
-        self._SectionsMacroDict = {}
-        GlobalData.gPlatformDefines = {}
-
-        # Get all macro and PCD which has straitforward value
-        self.__RetrievePcdValue()
-        self._Content = self._RawTable.GetAll()
-        self._ContentIndex = 0
-        while self._ContentIndex < len(self._Content) :
-            Id, self._ItemType, V1, V2, V3, S1, S2, Owner, BelongsToFile, self._From, \
-                LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
-
-            if self._From < 0:
-                self._FileWithError = self.MetaFile
-
-            self._ContentIndex += 1
-
-            self._Scope = [[S1, S2]]
-            self._LineIndex = LineStart - 1
-            self._ValueList = [V1, V2, V3]
-
-            try:
-                Processer[self._ItemType]()
-            except EvaluationException, Excpt:
-                # 
-                # Only catch expression evaluation error here. We need to report
-                # the precise number of line on which the error occurred
-                #
-                EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
-                                File=self._FileWithError, ExtraData=' '.join(self._ValueList), 
-                                Line=self._LineIndex+1)
-            except MacroException, Excpt:
-                EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
-                                File=self._FileWithError, ExtraData=' '.join(self._ValueList), 
-                                Line=self._LineIndex+1)
-
-            if self._ValueList == None:
-                continue 
-
-            NewOwner = self._IdMapping.get(Owner, -1)
-            self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
-            self._LastItem = self._Store(
-                                self._ItemType,
-                                self._ValueList[0],
-                                self._ValueList[1],
-                                self._ValueList[2],
-                                S1,
-                                S2,
-                                NewOwner,
-                                BelongsToFile,
-                                self._From,
-                                self._LineIndex+1,
-                                -1,
-                                self._LineIndex+1,
-                                -1,
-                                self._Enabled
-                                )
-            self._IdMapping[Id] = self._LastItem
-
-        RecordList = self._Table.GetAll()
-        
-        self._RawTable.Drop()
-        self._Table.Drop()
-        for Record in RecordList:
-            EccGlobalData.gDb.TblDsc.Insert(Record[1],Record[2],Record[3],Record[4],Record[5],Record[6],Record[7],Record[8],Record[9],Record[10],Record[11],Record[12],Record[13],Record[14])
-        GlobalData.gPlatformDefines.update(self._FileLocalMacros)
-        self._PostProcessed = True
-        self._Content = None
-
-    def __ProcessSectionHeader(self):
-        self._SectionName = self._ValueList[0]
-        if self._SectionName in self.DataType:
-            self._SectionType = self.DataType[self._SectionName]
-        else:
-            self._SectionType = MODEL_UNKNOWN
-
-    def __ProcessSubsectionHeader(self):
-        self._SubsectionName = self._ValueList[0]
-        if self._SubsectionName in self.DataType:
-            self._SubsectionType = self.DataType[self._SubsectionName]
-        else:
-            self._SubsectionType = MODEL_UNKNOWN
-
-    def __RetrievePcdValue(self):
-        Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0)
-        for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:
-            Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
-            # Only use PCD whose value is straitforward (no macro and PCD)
-            if self.SymbolPattern.findall(Value):
-                continue
-            Name = TokenSpaceGuid + '.' + PcdName
-            # Don't use PCD with different values.
-            if Name in self._Symbols and self._Symbols[Name] != Value:
-                self._Symbols.pop(Name)
-                continue 
-            self._Symbols[Name] = Value
-
-        Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0)
-        for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:
-            Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
-            # Only use PCD whose value is straitforward (no macro and PCD)
-            if self.SymbolPattern.findall(Value):
-                continue 
-            Name = TokenSpaceGuid+'.'+PcdName
-            # Don't use PCD with different values.
-            if Name in self._Symbols and self._Symbols[Name] != Value:
-                self._Symbols.pop(Name)
-                continue 
-            self._Symbols[Name] = Value
-
-    def __ProcessDefine(self):
-        if not self._Enabled:
-            return
-
-        Type, Name, Value = self._ValueList
-        Value = ReplaceMacro(Value, self._Macros, False)
-        if self._ItemType == MODEL_META_DATA_DEFINE:
-            if self._SectionType == MODEL_META_DATA_HEADER:
-                self._FileLocalMacros[Name] = Value
-            else:
-                SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
-                if SectionDictKey not in self._SectionsMacroDict:
-                    self._SectionsMacroDict[SectionDictKey] = {}
-                SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
-                SectionLocalMacros[Name] = Value
-        elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
-            GlobalData.gEdkGlobal[Name] = Value
-        
-        #
-        # Keyword in [Defines] section can be used as Macros
-        #
-        if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
-            self._FileLocalMacros[Name] = Value
-            
-        self._ValueList = [Type, Name, Value]
-
-    def __ProcessDirective(self):
-        Result = None
-        if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
-                              MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
-            Macros = self._Macros
-            Macros.update(GlobalData.gGlobalDefines)
-            try:
-                Result = ValueExpression(self._ValueList[1], Macros)()
-            except SymbolNotFound, Exc:
-                EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
-                Result = False
-            except WrnExpression, Excpt:
-                # 
-                # Catch expression evaluation warning here. We need to report
-                # the precise number of line and return the evaluation result
-                #
-                EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
-                                File=self._FileWithError, ExtraData=' '.join(self._ValueList), 
-                                Line=self._LineIndex+1)
-                Result = Excpt.result
-
-        if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
-                              MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
-                              MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
-            self._DirectiveStack.append(self._ItemType)
-            if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
-                Result = bool(Result)
-            else:
-                Macro = self._ValueList[1]
-                Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
-                Result = Macro in self._Macros
-                if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
-                    Result = not Result
-            self._DirectiveEvalStack.append(Result)
-        elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
-            self._DirectiveStack.append(self._ItemType)
-            self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
-            self._DirectiveEvalStack.append(bool(Result))
-        elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
-            self._DirectiveStack[-1] = self._ItemType
-            self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
-        elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
-            # Back to the nearest !if/!ifdef/!ifndef
-            while self._DirectiveStack:
-                self._DirectiveEvalStack.pop()
-                Directive = self._DirectiveStack.pop()
-                if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
-                                 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
-                                 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
-                                 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
-                    break
-        elif self._ItemType == MODEL_META_DATA_INCLUDE:
-            # The included file must be relative to workspace or same directory as DSC file
-            __IncludeMacros = {}
-            #
-            # Allow using system environment variables  in path after !include
-            #
-            __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
-            if "ECP_SOURCE" in GlobalData.gGlobalDefines.keys():
-                __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']
-            #
-            # During GenFds phase call DSC parser, will go into this branch.
-            #
-            elif "ECP_SOURCE" in GlobalData.gCommandLineDefines.keys():
-                __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']
-                
-            __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']
-            __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']
-            #
-            # Allow using MACROs comes from [Defines] section to keep compatible. 
-            #
-            __IncludeMacros.update(self._Macros)
-            
-            IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
-            #
-            # First search the include file under the same directory as DSC file
-            #
-            IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
-            ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
-            if ErrorCode != 0:
-                #
-                # Also search file under the WORKSPACE directory
-                #
-                IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
-                ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
-                if ErrorCode != 0:
-                    EdkLogger.error('parser', ErrorCode, File=self._FileWithError, 
-                                    Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2)
-
-            self._FileWithError = IncludedFile1
-
-            IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True)
-            Owner = self._Content[self._ContentIndex-1][0]
-            Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable, 
-                               Owner=Owner, From=Owner)
-
-            # set the parser status with current status
-            Parser._SectionName = self._SectionName
-            Parser._SectionType = self._SectionType
-            Parser._Scope = self._Scope
-            Parser._Enabled = self._Enabled
-            # Parse the included file
-            Parser.Start()
-
-            # update current status with sub-parser's status
-            self._SectionName = Parser._SectionName
-            self._SectionType = Parser._SectionType
-            self._Scope       = Parser._Scope
-            self._Enabled     = Parser._Enabled
-
-            # Insert all records in the table for the included file into dsc file table
-            Records = IncludedFileTable.GetAll()
-            if Records:
-                self._Content[self._ContentIndex:self._ContentIndex] = Records
-                self._Content.pop(self._ContentIndex-1)
-                self._ValueList = None
-                self._ContentIndex -= 1
-                
-    def __ProcessSkuId(self):
-        self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
-                           for Value in self._ValueList]
-
-    def __ProcessLibraryInstance(self):
-        self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
-
-    def __ProcessLibraryClass(self):
-        self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
-
-    def __ProcessPcd(self):
-        ValueList = GetSplitValueList(self._ValueList[2])
-        #
-        # PCD value can be an expression
-        #
-        if len(ValueList) > 1 and ValueList[1] == 'VOID*':
-            PcdValue = ValueList[0]      
-            try:
-                ValueList[0] = ValueExpression(PcdValue, self._Macros)(True)
-            except WrnExpression, Value:
-                ValueList[0] = Value.result          
-        else:
-            PcdValue = ValueList[-1]
-            try:
-                ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True)
-            except WrnExpression, Value:
-                ValueList[-1] = Value.result
-            
-            if ValueList[-1] == 'True':
-                ValueList[-1] = '1'
-            if ValueList[-1] == 'False':
-                ValueList[-1] = '0'      
-
-        self._ValueList[2] = '|'.join(ValueList)
-
-    def __ProcessComponent(self):
-        self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
-
-    def __ProcessSourceOverridePath(self):
-        self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
-
-    def __ProcessBuildOption(self):
-        self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
-                           for Value in self._ValueList]
-
-    _SectionParser = {
-        MODEL_META_DATA_HEADER                          :   _DefineParser,
-        MODEL_EFI_SKU_ID                                :   _SkuIdParser,
-        MODEL_EFI_LIBRARY_INSTANCE                      :   _LibraryInstanceParser,
-        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                    :   _BuildOptionParser,
-        MODEL_UNKNOWN                                   :   MetaFileParser._Skip,
-        MODEL_META_DATA_USER_EXTENSION                  :   MetaFileParser._Skip,
-        MODEL_META_DATA_SECTION_HEADER                  :   MetaFileParser._SectionHeaderParser,
-        MODEL_META_DATA_SUBSECTION_HEADER               :   _SubsectionHeaderParser,
-    }
-
-    _Macros     = property(_GetMacros)
-
-## 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_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,
-        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):
-        # prevent re-initialization
-        if hasattr(self, "_Table"):
-            return
-        MetaFileParser.__init__(self, FilePath, FileType, Table)
-        self._Comments = []
-        self._Version = 0x00010005  # Only EDK2 dec file is supported
-        self.TblFile = EccGlobalData.gDb.TblFile
-        self.FileID = -1
-
-    ## Parser starter
-    def Start(self):
-        Content = ''
-        try:
-            Content = open(str(self.MetaFile), 'r').readlines()
-        except:
-            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
-
-        #
-        # Insert a record for file
-        #
-        Filename = NormPath(self.MetaFile)
-        FileID = self.TblFile.GetFileId(Filename)
-        if FileID:
-            self.FileID = FileID
-        else:
-            self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC)
-        
-        for Index in range(0, len(Content)):
-            Line, Comment = CleanString2(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 len(self._SectionType) == 0:
-                self._Comments = []
-                continue
-
-            # section content
-            self._ValueList = ['','','']
-            self._SectionParser[self._SectionType[0]](self)
-            if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
-                self._ItemType = -1
-                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[-1],
-                    self.FileID,
-                    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,
-                        self.FileID,
-                        LineNo,
-                        -1,
-                        LineNo,
-                        -1,
-                        0
-                        )
-            self._Comments = []
-        self._Done()
-
-    def _GetApplicableSectionMacro(self):
-        Macros = {}
-        for S1, S2, SectionType in self._Scope:
-            for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", S2), (S1, "COMMON"), (S1, S2)]:
-                if (SectionType, Scope1, Scope2) in self._SectionsMacroDict:
-                    Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)])
-        return Macros
-
-    ## 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
-    @ParseMacro
-    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]
-        #Parse the Guid value format
-        GuidValueList = TokenList[1].strip(' {}').split(',')
-        Index = 0
-        HexList = []
-        if len(GuidValueList) == 11:
-            for GuidValue in GuidValueList:
-                GuidValue = GuidValue.strip()
-                if GuidValue.startswith('0x') or GuidValue.startswith('0X'):
-                    HexList.append('0x' + str(GuidValue[2:]))
-                    Index += 1
-                    continue
-                else:
-                    if GuidValue.startswith('{'):
-                        HexList.append('0x' + str(GuidValue[3:]))
-                        Index += 1
-            self._ValueList[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList[0], HexList[1], HexList[2],HexList[3],HexList[4],HexList[5],HexList[6],HexList[7],HexList[8],HexList[9],HexList[10])
-        else:
-            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] = ''
-
-    ## PCD sections parser
-    #
-    #   [PcdsFixedAtBuild]
-    #   [PcdsPatchableInModule]
-    #   [PcdsFeatureFlag]
-    #   [PcdsDynamicEx
-    #   [PcdsDynamic]
-    #
-    @ParseMacro
-    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,
-    }
-
-
-## FdfObject
-#
-# This class defined basic Fdf object which is used by inheriting
-# 
-# @param object:       Inherited from object class
-#
-class FdfObject(object):
-    def __init__(self):
-        object.__init__()
-
-## Fdf
-#
-# This class defined the structure used in Fdf object
-# 
-# @param FdfObject:     Inherited from FdfObject class
-# @param Filename:      Input value for Ffilename of Fdf file, default is None
-# @param WorkspaceDir:  Input value for current workspace directory, default is None
-#
-class Fdf(FdfObject):
-    def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None):
-        self.WorkspaceDir = WorkspaceDir
-        self.IsToDatabase = IsToDatabase
-        
-        self.Cur = Database.Cur
-        self.TblFile = Database.TblFile
-        self.TblFdf = Database.TblFdf
-        self.FileID = -1
-        self.FileList = {}
-
-        #
-        # Load Fdf file if filename is not None
-        #
-        if Filename != None:
-            self.LoadFdfFile(Filename)
-
-    #
-    # Insert a FDF file record into database
-    #
-    def InsertFile(self, Filename):
-        FileID = -1
-        Filename = NormPath(Filename)
-        if Filename not in self.FileList:
-            FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF)
-            self.FileList[Filename] = FileID
-
-        return self.FileList[Filename]
-            
-    
-    ## Load Fdf file
-    #
-    # Load the file if it exists
-    #
-    # @param Filename:  Input value for filename of Fdf file
-    #
-    def LoadFdfFile(self, Filename):     
-        FileList = []
-        #
-        # Parse Fdf file
-        #
-        Filename = NormPath(Filename)
-        Fdf = FdfParser(Filename)
-        Fdf.ParseFile()
-
-        #
-        # Insert inf file and pcd information
-        #
-        if self.IsToDatabase:
-            (Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \
-            (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
-            for Index in range(0, len(Fdf.Profile.PcdDict)):
-                pass
-            for Key in Fdf.Profile.PcdDict.keys():
-                Model = MODEL_PCD
-                Value1 = Key[1]
-                Value2 = Key[0]
-                FileName = Fdf.Profile.PcdFileLineDict[Key][0]
-                StartLine = Fdf.Profile.PcdFileLineDict[Key][1]
-                BelongsToFile = self.InsertFile(FileName)
-                self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
-            for Index in range(0, len(Fdf.Profile.InfList)):
-                Model = MODEL_META_DATA_COMPONENT
-                Value1 = Fdf.Profile.InfList[Index]
-                Value2 = ''
-                FileName = Fdf.Profile.InfFileLineList[Index][0]
-                StartLine = Fdf.Profile.InfFileLineList[Index][1]
-                BelongsToFile = self.InsertFile(FileName)
-                self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
-
-##
-#
-# 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 - 2015, Intel Corporation. All rights reserved.<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
+import Common.LongFilePathOs as os\r
+import re\r
+import time\r
+import copy\r
+\r
+import Common.EdkLogger as EdkLogger\r
+import Common.GlobalData as GlobalData\r
+import EccGlobalData\r
+import EccToolError\r
+\r
+from CommonDataClass.DataClass import *\r
+from Common.DataType import *\r
+from Common.String import *\r
+from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData\r
+from Common.Expression import *\r
+from CommonDataClass.Exceptions import *\r
+\r
+from MetaFileTable import MetaFileStorage\r
+from GenFds.FdfParser import FdfParser\r
+from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from Common.LongFilePathSupport import CodecOpenLongFilePath\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
+        self._ItemType = MODEL_META_DATA_DEFINE\r
+        # DEFINE defined macros\r
+        if Type == TAB_DSC_DEFINES_DEFINE:\r
+            if type(self) == DecParser:\r
+                if MODEL_META_DATA_HEADER in self._SectionType:\r
+                    self._FileLocalMacros[Name] = Value\r
+                else:\r
+                    for Scope in self._Scope:\r
+                        self._SectionsMacroDict.setdefault((Scope[2], Scope[0], Scope[1]), {})[Name] = Value\r
+            elif self._SectionType == MODEL_META_DATA_HEADER:\r
+                self._FileLocalMacros[Name] = Value\r
+            else:\r
+                SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]\r
+                if SectionDictKey not in self._SectionsMacroDict:\r
+                    self._SectionsMacroDict[SectionDictKey] = {}\r
+                SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]\r
+                SectionLocalMacros[Name] = Value\r
+        # EDK_GLOBAL defined macros\r
+        elif type(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      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
+    def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):\r
+        self._Table = Table\r
+        self._RawTable = Table\r
+        self._FileType = FileType\r
+        self.MetaFile = FilePath\r
+        self._Defines = {}\r
+        self._FileLocalMacros = {}\r
+        self._SectionsMacroDict = {}\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
+        # UNI object and extra UNI object\r
+        self._UniObj = None\r
+        self._UniExtraObj = None\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
+    ## 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 type(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._RawTable.Query(*DataInfo)\r
+\r
+        # Do post-process if necessary\r
+        if not self._PostProcessed:\r
+            self._PostProcess()\r
+\r
+        return self._Table.Query(*DataInfo)\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 type(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
+        if self._SectionName == TAB_USER_EXTENSIONS.upper() and self._CurrentLine.upper().endswith('.UNI'):\r
+            if EccGlobalData.gConfig.UniCheckHelpInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
+                ExtraUni = self._CurrentLine.strip()\r
+                ExtraUniFile = os.path.join(os.path.dirname(self.MetaFile), ExtraUni)\r
+                IsModuleUni = self.MetaFile.upper().endswith('.INF')\r
+                self._UniExtraObj = UniParser(ExtraUniFile, IsExtraUni=True, IsModuleUni=IsModuleUni)\r
+                self._UniExtraObj.Start()\r
+        else:\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
+    ## 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)\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
+            else:\r
+                self._SectionType = MODEL_UNKNOWN\r
+                EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,\r
+                                Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
+            # S1 is always Arch\r
+            if len(ItemList) > 1:\r
+                S1 = ItemList[1].upper()\r
+            else:\r
+                S1 = 'COMMON'\r
+            ArchList.add(S1)\r
+            # S2 may be Platform or ModuleType\r
+            if len(ItemList) > 2:\r
+                S2 = ItemList[2].upper()\r
+            else:\r
+                S2 = 'COMMON'\r
+            self._Scope.append([S1, S2])\r
+\r
+        # 'COMMON' must not be used with specific ARCHs at the same section\r
+        if '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
+        # Sometimes, we need to make differences between EDK and EDK2 modules \r
+        if Name == 'INF_VERSION':\r
+            try:\r
+                self._Version = int(Value, 0)\r
+            except:\r
+                EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",\r
+                                ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
+        elif Name == 'MODULE_UNI_FILE':\r
+            UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)\r
+            if os.path.exists(UniFile):\r
+                self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=True)\r
+                self._UniObj.Start()\r
+            else:\r
+                EdkLogger.error('Parser', FILE_NOT_FOUND, "Module UNI file %s is missing." % Value,\r
+                                ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1,\r
+                                RaiseError=False)\r
+        elif Name == 'PACKAGE_UNI_FILE':\r
+            UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)\r
+            if os.path.exists(UniFile):\r
+                self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=False)\r
+        \r
+        if type(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
+        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 type(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
+\r
+    def _GetMacros(self):\r
+        Macros = {}\r
+        Macros.update(self._FileLocalMacros)\r
+        Macros.update(self._GetApplicableSectionMacro())\r
+        return Macros\r
+\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
+        for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", self._Scope[0][1]),\r
+                               (self._Scope[0][0], "COMMON"), (self._Scope[0][0], self._Scope[0][1])]:\r
+            if (self._SectionType, Scope1, Scope2) in self._SectionsMacroDict:\r
+                Macros.update(self._SectionsMacroDict[(self._SectionType, Scope1, Scope2)])\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      Table           Database used to retrieve module/package information\r
+    #   @param      Macros          Macros used for replacement in file\r
+    #\r
+    def __init__(self, FilePath, FileType, Table):\r
+        # prevent re-initialization\r
+        if hasattr(self, "_Table"):\r
+            return\r
+        MetaFileParser.__init__(self, FilePath, FileType, Table)\r
+        self.TblFile = EccGlobalData.gDb.TblFile\r
+        self.FileID = -1\r
+\r
+    ## Parser starter\r
+    def Start(self):\r
+        NmakeLine = ''\r
+        Content = ''\r
+        Usage = ''\r
+        try:\r
+            Content = open(str(self.MetaFile), 'r').readlines()\r
+        except:\r
+            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
+        #\r
+        # Insert a record for file\r
+        #\r
+        Filename = NormPath(self.MetaFile)\r
+        FileID = self.TblFile.GetFileId(Filename)\r
+        if FileID:\r
+            self.FileID = FileID\r
+        else:\r
+            self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_INF)\r
+            \r
+        # parse the file line by line\r
+        IsFindBlockComment = False\r
+\r
+        for Index in range(0, len(Content)):\r
+            if self._SectionType in [MODEL_EFI_GUID,\r
+                                     MODEL_EFI_PROTOCOL,\r
+                                     MODEL_EFI_PPI,\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
+                Line = Content[Index].strip()\r
+                if Line.startswith(TAB_SPECIAL_COMMENT):\r
+                    Usage += ' ' + Line[Line.find(TAB_SPECIAL_COMMENT):]\r
+                    continue\r
+                elif Line.startswith(TAB_COMMENT_SPLIT):\r
+                    continue\r
+                elif Line.find(TAB_COMMENT_SPLIT) > 0:\r
+                    Usage += ' ' + Line[Line.find(TAB_COMMENT_SPLIT):]\r
+                    Line = Line[:Line.find(TAB_COMMENT_SPLIT)]\r
+            else:\r
+            # skip empty, commented, block commented lines\r
+                Line = CleanString(Content[Index], AllowCppStyleComment=True)\r
+                Usage = ''\r
+            NextLine = ''\r
+            if Index + 1 < len(Content):\r
+                NextLine = CleanString(Content[Index + 1])\r
+            if Line == '':\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
+                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
+                continue\r
+            #\r
+            # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,\r
+            # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
+            #\r
+            self._ValueList[0] = self._ValueList[0].replace('/', '\\')\r
+            Usage = Usage.strip()\r
+            for Arch, Platform in self._Scope:\r
+                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.FileID,\r
+                            self._LineIndex+1,\r
+                            -1,\r
+                            self._LineIndex+1,\r
+                            -1,\r
+                            0,\r
+                            Usage\r
+                            )\r
+            Usage = ''\r
+        if IsFindBlockComment:\r
+            EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */", \r
+                            File=self.MetaFile)\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
+\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._Skip,\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_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_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
+        "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
+    ]\r
+\r
+    SubSectionDefineKeywords = [\r
+        "FILE_GUID"\r
+    ]\r
+\r
+    SymbolPattern = ValueExpression.SymbolPattern\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      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
+    def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):\r
+        # prevent re-initialization\r
+        if hasattr(self, "_Table"):\r
+            return\r
+        MetaFileParser.__init__(self, FilePath, FileType, 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
+        # 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
+        self.TblFile = EccGlobalData.gDb.TblFile\r
+        self.FileID = -1\r
+\r
+    ## Parser starter\r
+    def Start(self):\r
+        Content = ''\r
+        try:\r
+            Content = open(str(self.MetaFile.Path), 'r').readlines()\r
+        except:\r
+            EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
+        #\r
+        # Insert a record for file\r
+        #\r
+        Filename = NormPath(self.MetaFile.Path)\r
+        FileID = self.TblFile.GetFileId(Filename)\r
+        if FileID:\r
+            self.FileID = FileID\r
+        else:\r
+            self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC)\r
+        \r
+        \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
+                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
+                self._DirectiveParser()\r
+                continue\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 in self._Scope:\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
+                                        self._Owner[-1],\r
+                                        self.FileID,\r
+                                        self._From,\r
+                                        self._LineIndex+1,\r
+                                        -1,\r
+                                        self._LineIndex+1,\r
+                                        -1,\r
+                                        self._Enabled\r
+                                        )\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
+        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
+        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 != MODEL_META_DATA_INCLUDE:\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
+        elif self._From > 0:\r
+            EdkLogger.error('Parser', FORMAT_INVALID,\r
+                            "No '!include' allowed in included file",\r
+                            ExtraData=self._CurrentLine, File=self.MetaFile, \r
+                            Line=self._LineIndex+1)\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
+        self._LastItem = self._Store(\r
+                                ItemType,\r
+                                self._ValueList[0],\r
+                                self._ValueList[1],\r
+                                self._ValueList[2],\r
+                                'COMMON',\r
+                                'COMMON',\r
+                                self._Owner[-1],\r
+                                self.FileID,\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
+        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) != 2:\r
+            EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<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
+    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
+        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
+            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
+        # 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
+    ## [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
+        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
+        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 = dict( [('ARCH','IA32'), ('FAMILY','MSFT'),('TOOL_CHAIN_TAG','VS2008x86'),('TARGET','DEBUG')])\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
+        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_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._Skip,\r
+            MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR     :   self._Skip,\r
+        }\r
+        \r
+        self._RawTable = self._Table\r
+        self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)\r
+        self._DirectiveStack = []\r
+        self._DirectiveEvalStack = []\r
+        self._FileWithError = self.MetaFile\r
+        self._FileLocalMacros = {}\r
+        self._SectionsMacroDict = {}\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
+        while self._ContentIndex < len(self._Content) :\r
+            Id, self._ItemType, V1, V2, V3, S1, S2, Owner, BelongsToFile, 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]]\r
+            self._LineIndex = LineStart - 1\r
+            self._ValueList = [V1, V2, V3]\r
+\r
+            try:\r
+                Processer[self._ItemType]()\r
+            except EvaluationException, 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
+                pass\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, 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
+                                NewOwner,\r
+                                BelongsToFile,\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
+        RecordList = self._Table.GetAll()\r
+        \r
+        self._RawTable.Drop()\r
+        self._Table.Drop()\r
+        for Record in RecordList:\r
+            EccGlobalData.gDb.TblDsc.Insert(Record[1],Record[2],Record[3],Record[4],Record[5],Record[6],Record[7],Record[8],Record[9],Record[10],Record[11],Record[12],Record[13],Record[14])\r
+        GlobalData.gPlatformDefines.update(self._FileLocalMacros)\r
+        self._PostProcessed = True\r
+        self._Content = None\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
+        Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0)\r
+        for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:\r
+            Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)\r
+            # Only use PCD whose value is straitforward (no macro and PCD)\r
+            if self.SymbolPattern.findall(Value):\r
+                continue\r
+            Name = TokenSpaceGuid + '.' + PcdName\r
+            # Don't use PCD with different values.\r
+            if Name in self._Symbols and self._Symbols[Name] != Value:\r
+                self._Symbols.pop(Name)\r
+                continue \r
+            self._Symbols[Name] = Value\r
+\r
+        Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0)\r
+        for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:\r
+            Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)\r
+            # Only use PCD whose value is straitforward (no macro and PCD)\r
+            if self.SymbolPattern.findall(Value):\r
+                continue \r
+            Name = TokenSpaceGuid+'.'+PcdName\r
+            # Don't use PCD with different values.\r
+            if Name in self._Symbols and self._Symbols[Name] != Value:\r
+                self._Symbols.pop(Name)\r
+                continue \r
+            self._Symbols[Name] = Value\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
+        if self._ItemType == MODEL_META_DATA_DEFINE:\r
+            if self._SectionType == MODEL_META_DATA_HEADER:\r
+                self._FileLocalMacros[Name] = Value\r
+            else:\r
+                SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]\r
+                if SectionDictKey not in self._SectionsMacroDict:\r
+                    self._SectionsMacroDict[SectionDictKey] = {}\r
+                SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]\r
+                SectionLocalMacros[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, Exc:\r
+                EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
+                Result = False\r
+            except WrnExpression, 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
+            except BadExpression, Exc:\r
+                EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
+                Result = False\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[-1] = self._ItemType\r
+            self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\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_ELSE,\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.keys():\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.keys():\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
+            IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True)\r
+            Owner = self._Content[self._ContentIndex-1][0]\r
+            Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable, \r
+                               Owner=Owner, From=Owner)\r
+\r
+            # set the parser status with current status\r
+            Parser._SectionName = self._SectionName\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
+            # update current status with sub-parser's status\r
+            self._SectionName = Parser._SectionName\r
+            self._SectionType = Parser._SectionType\r
+            self._Scope       = Parser._Scope\r
+            self._Enabled     = Parser._Enabled\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
+\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
+        ValueList = GetSplitValueList(self._ValueList[2])\r
+        #\r
+        # PCD value can be an expression\r
+        #\r
+        if len(ValueList) > 1 and ValueList[1] == 'VOID*':\r
+            PcdValue = ValueList[0]      \r
+            try:\r
+                ValueList[0] = ValueExpression(PcdValue, self._Macros)(True)\r
+            except WrnExpression, Value:\r
+                ValueList[0] = Value.result          \r
+        else:\r
+            PcdValue = ValueList[-1]\r
+            try:\r
+                ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True)\r
+            except WrnExpression, Value:\r
+                ValueList[-1] = Value.result\r
+            \r
+            if ValueList[-1] == 'True':\r
+                ValueList[-1] = '1'\r
+            if ValueList[-1] == 'False':\r
+                ValueList[-1] = '0'      \r
+\r
+        self._ValueList[2] = '|'.join(ValueList)\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_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._Skip,\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
+    }\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      Table           Database used to retrieve module/package information\r
+    #   @param      Macros          Macros used for replacement in file\r
+    #\r
+    def __init__(self, FilePath, FileType, Table):\r
+        # prevent re-initialization\r
+        if hasattr(self, "_Table"):\r
+            return\r
+        MetaFileParser.__init__(self, FilePath, FileType, Table)\r
+        self._Comments = []\r
+        self._Version = 0x00010005  # Only EDK2 dec file is supported\r
+        self.TblFile = EccGlobalData.gDb.TblFile\r
+        self.FileID = -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
+        #\r
+        # Insert a record for file\r
+        #\r
+        Filename = NormPath(self.MetaFile)\r
+        FileID = self.TblFile.GetFileId(Filename)\r
+        if FileID:\r
+            self.FileID = FileID\r
+        else:\r
+            self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC)\r
+        \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
+                self._Comments = []\r
+                continue\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.FileID,\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
+                        self.FileID,\r
+                        LineNo,\r
+                        -1,\r
+                        LineNo,\r
+                        -1,\r
+                        0\r
+                        )\r
+            self._Comments = []\r
+        self._Done()\r
+\r
+    def _GetApplicableSectionMacro(self):\r
+        Macros = {}\r
+        for S1, S2, SectionType in self._Scope:\r
+            for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", S2), (S1, "COMMON"), (S1, S2)]:\r
+                if (SectionType, Scope1, Scope2) in self._SectionsMacroDict:\r
+                    Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)])\r
+        return Macros\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
+        for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):\r
+            if Item == '':\r
+                continue\r
+            ItemList = GetSplitValueList(Item, TAB_SPLIT)\r
+\r
+            # different types of PCD are permissible in one section\r
+            self._SectionName = ItemList[0].upper()\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.warn("Parser", "Unrecognized section", File=self.MetaFile,\r
+                                Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
+                continue\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 = 'COMMON'\r
+            ArchList.add(S1)\r
+            # S2 may be Platform or ModuleType\r
+            if len(ItemList) > 2:\r
+                S2 = ItemList[2].upper()\r
+            else:\r
+                S2 = 'COMMON'\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 '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
+    ## [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
+        #Parse the Guid value format\r
+        GuidValueList = TokenList[1].strip(' {}').split(',')\r
+        Index = 0\r
+        HexList = []\r
+        if len(GuidValueList) == 11:\r
+            for GuidValue in GuidValueList:\r
+                GuidValue = GuidValue.strip()\r
+                if GuidValue.startswith('0x') or GuidValue.startswith('0X'):\r
+                    HexList.append('0x' + str(GuidValue[2:]))\r
+                    Index += 1\r
+                    continue\r
+                else:\r
+                    if GuidValue.startswith('{'):\r
+                        GuidValue = GuidValue.lstrip(' {')\r
+                        HexList.append('0x' + str(GuidValue[2:]))\r
+                        Index += 1\r
+            self._ValueList[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList[0], HexList[1], HexList[2],HexList[3],HexList[4],HexList[5],HexList[6],HexList[7],HexList[8],HexList[9],HexList[10])\r
+        else:\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] = ''\r
+\r
+    ## PCD sections parser\r
+    #\r
+    #   [PcdsFixedAtBuild]\r
+    #   [PcdsPatchableInModule]\r
+    #   [PcdsFeatureFlag]\r
+    #   [PcdsDynamicEx\r
+    #   [PcdsDynamic]\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
+        # 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 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    = GetSplitValueList(ptrValueList)\r
+            ValueList[0] = PtrValue[0]\r
+        else:\r
+            ValueList = GetSplitValueList(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
+        # 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 EccGlobalData.gConfig.UniCheckPCDInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
+            # check Description, Prompt information\r
+            PatternDesc = re.compile('##\s*([\x21-\x7E\s]*)', re.S)\r
+            PatternPrompt = re.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re.S)\r
+            Description = None\r
+            Prompt = None\r
+            # check @ValidRange, @ValidList and @Expression format valid\r
+            ErrorCodeValid = '0x0 <= %s <= 0xFFFFFFFF'\r
+            PatternValidRangeIn = '(NOT)?\s*(\d+\s*-\s*\d+|0[xX][a-fA-F0-9]+\s*-\s*0[xX][a-fA-F0-9]+|LT\s*\d+|LT\s*0[xX][a-fA-F0-9]+|GT\s*\d+|GT\s*0[xX][a-fA-F0-9]+|LE\s*\d+|LE\s*0[xX][a-fA-F0-9]+|GE\s*\d+|GE\s*0[xX][a-fA-F0-9]+|XOR\s*\d+|XOR\s*0[xX][a-fA-F0-9]+|EQ\s*\d+|EQ\s*0[xX][a-fA-F0-9]+)'\r
+            PatternValidRng = re.compile('^' + '(NOT)?\s*' + PatternValidRangeIn + '$')\r
+            for Comment in self._Comments:\r
+                Comm = Comment[0].strip()\r
+                if not Comm:\r
+                    continue\r
+                if not Description:\r
+                    Description = PatternDesc.findall(Comm)\r
+                if not Prompt:\r
+                    Prompt = PatternPrompt.findall(Comm)\r
+                if Comm[0] == '#':\r
+                    ValidFormt = Comm.lstrip('#')\r
+                    ValidFormt = ValidFormt.lstrip()\r
+                    if ValidFormt[0:11] == '@ValidRange':\r
+                        ValidFormt = ValidFormt[11:]\r
+                        ValidFormt = ValidFormt.lstrip()\r
+                        try:\r
+                            ErrorCode, Expression = ValidFormt.split('|', 1)\r
+                        except ValueError:\r
+                            ErrorCode = '0x0'\r
+                            Expression = ValidFormt\r
+                        ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
+                        try:\r
+                            if not eval(ErrorCodeValid % ErrorCode):\r
+                                EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
+                        except:\r
+                            EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
+                        if not PatternValidRng.search(Expression):\r
+                            EdkLogger.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression, TokenList[0]))\r
+                    if ValidFormt[0:10] == '@ValidList':\r
+                        ValidFormt = ValidFormt[10:]\r
+                        ValidFormt = ValidFormt.lstrip()\r
+                        try:\r
+                            ErrorCode, Expression = ValidFormt.split('|', 1)\r
+                        except ValueError:\r
+                            ErrorCode = '0x0'\r
+                            Expression = ValidFormt\r
+                        ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
+                        try:\r
+                            if not eval(ErrorCodeValid % ErrorCode):\r
+                                EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
+                        except:\r
+                            EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
+                        Values = Expression.split(',')\r
+                        for Value in Values:\r
+                            Value = Value.strip()\r
+                            try:\r
+                                eval(Value)\r
+                            except:\r
+                                EdkLogger.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList[0], Value))\r
+                                break\r
+                    if ValidFormt[0:11] == '@Expression':\r
+                        ValidFormt = ValidFormt[11:]\r
+                        ValidFormt = ValidFormt.lstrip()\r
+                        try:\r
+                            ErrorCode, Expression = ValidFormt.split('|', 1)\r
+                        except ValueError:\r
+                            ErrorCode = '0x0'\r
+                            Expression = ValidFormt\r
+                        ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
+                        try:\r
+                            if not eval(ErrorCodeValid % ErrorCode):\r
+                                EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
+                        except:\r
+                            EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
+                        if not Expression:\r
+                            EdkLogger.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList[0])\r
+            if not Description:\r
+                EdkLogger.warn('Parser', 'PCD %s Description information is not provided.' % TokenList[0])\r
+            if not Prompt:\r
+                EdkLogger.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList[0])\r
+            # check Description, Prompt localization information\r
+            if self._UniObj:\r
+                self._UniObj.CheckPcdInfo(TokenList[0])\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
+        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._Skip,\r
+    }\r
+\r
+\r
+## Fdf\r
+#\r
+# This class defined the structure used in Fdf object\r
+# \r
+# @param Filename:      Input value for Ffilename of Fdf file, default is None\r
+# @param WorkspaceDir:  Input value for current workspace directory, default is None\r
+#\r
+class Fdf(object):\r
+    def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None):\r
+        self.WorkspaceDir = WorkspaceDir\r
+        self.IsToDatabase = IsToDatabase\r
+        \r
+        self.Cur = Database.Cur\r
+        self.TblFile = Database.TblFile\r
+        self.TblFdf = Database.TblFdf\r
+        self.FileID = -1\r
+        self.FileList = {}\r
+\r
+        #\r
+        # Load Fdf file if filename is not None\r
+        #\r
+        if Filename is not None:\r
+            try:\r
+                self.LoadFdfFile(Filename)\r
+            except Exception:\r
+                pass\r
+\r
+    #\r
+    # Insert a FDF file record into database\r
+    #\r
+    def InsertFile(self, Filename):\r
+        FileID = -1\r
+        Filename = NormPath(Filename)\r
+        if Filename not in self.FileList:\r
+            FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF)\r
+            self.FileList[Filename] = FileID\r
+\r
+        return self.FileList[Filename]\r
+            \r
+    \r
+    ## Load Fdf file\r
+    #\r
+    # Load the file if it exists\r
+    #\r
+    # @param Filename:  Input value for filename of Fdf file\r
+    #\r
+    def LoadFdfFile(self, Filename):     \r
+        FileList = []\r
+        #\r
+        # Parse Fdf file\r
+        #\r
+        Filename = NormPath(Filename)\r
+        Fdf = FdfParser(Filename)\r
+        Fdf.ParseFile()\r
+\r
+        #\r
+        # Insert inf file and pcd information\r
+        #\r
+        if self.IsToDatabase:\r
+            (Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \\r
+            (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)\r
+            for Index in range(0, len(Fdf.Profile.PcdDict)):\r
+                pass\r
+            for Key in Fdf.Profile.PcdDict.keys():\r
+                Model = MODEL_PCD\r
+                Value1 = Key[1]\r
+                Value2 = Key[0]\r
+                FileName = Fdf.Profile.PcdFileLineDict[Key][0]\r
+                StartLine = Fdf.Profile.PcdFileLineDict[Key][1]\r
+                BelongsToFile = self.InsertFile(FileName)\r
+                self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)\r
+            for Index in range(0, len(Fdf.Profile.InfList)):\r
+                Model = MODEL_META_DATA_COMPONENT\r
+                Value1 = Fdf.Profile.InfList[Index]\r
+                Value2 = ''\r
+                FileName = Fdf.Profile.InfFileLineList[Index][0]\r
+                StartLine = Fdf.Profile.InfFileLineList[Index][1]\r
+                BelongsToFile = self.InsertFile(FileName)\r
+                self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)\r
+\r
+class UniParser(object):\r
+    # IsExtraUni defined the UNI file is Module UNI or extra Module UNI\r
+    # IsModuleUni defined the UNI file is Module UNI or Package UNI\r
+    def __init__(self, FilePath, IsExtraUni=False, IsModuleUni=True):\r
+        self.FilePath = FilePath\r
+        self.FileName = os.path.basename(FilePath)\r
+        self.IsExtraUni = IsExtraUni\r
+        self.IsModuleUni = IsModuleUni\r
+        self.FileIn = None\r
+        self.Missing = []\r
+        self.__read()\r
+    \r
+    def __read(self):\r
+        try:\r
+            self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_8').read()\r
+        except UnicodeError:\r
+            self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16').read()\r
+        except UnicodeError:\r
+            self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16_le').read()\r
+        except IOError:\r
+            self.FileIn = ""\r
+    \r
+    def Start(self):\r
+        if self.IsModuleUni:\r
+            if self.IsExtraUni:\r
+                ModuleName = self.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')\r
+                self.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName)\r
+            else:\r
+                ModuleAbstract = self.CheckKeyValid('STR_MODULE_ABSTRACT')\r
+                self.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract)\r
+                ModuleDescription = self.CheckKeyValid('STR_MODULE_DESCRIPTION')\r
+                self.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription)\r
+        else:\r
+            if self.IsExtraUni:\r
+                PackageName = self.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')\r
+                self.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName)\r
+            else:\r
+                PackageAbstract = self.CheckKeyValid('STR_PACKAGE_ABSTRACT')\r
+                self.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract)\r
+                PackageDescription = self.CheckKeyValid('STR_PACKAGE_DESCRIPTION')\r
+                self.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription)\r
+                \r
+    def CheckKeyValid(self, Key, Contents=None):\r
+        if not Contents:\r
+            Contents = self.FileIn\r
+        KeyPattern = re.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key, re.S)\r
+        if KeyPattern.search(Contents):\r
+            return True\r
+        return False\r
+    \r
+    def CheckPcdInfo(self, PcdCName):\r
+        PromptKey = 'STR_%s_PROMPT' % PcdCName.replace('.', '_')\r
+        PcdPrompt = self.CheckKeyValid(PromptKey)\r
+        self.PrintLog(PromptKey, PcdPrompt)\r
+        HelpKey = 'STR_%s_HELP' % PcdCName.replace('.', '_')\r
+        PcdHelp = self.CheckKeyValid(HelpKey)\r
+        self.PrintLog(HelpKey, PcdHelp)\r
+    \r
+    def PrintLog(self, Key, Value):\r
+        if not Value and Key not in self.Missing:\r
+            Msg = '%s is missing in the %s file.' % (Key, self.FileName)\r
+            EdkLogger.warn('Parser', Msg)\r
+            EccGlobalData.gDb.TblReport.Insert(EccToolError.ERROR_GENERAL_CHECK_UNI_HELP_INFO, OtherMsg=Msg, BelongsToTable='File', BelongsToItem=-2)\r
+            self.Missing.append(Key)\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