]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Workspace/MetaFileParser.py
Sync EDKII BaseTools to BaseTools project r2093.
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileParser.py
index eb2e038b5d10091bddfb336a49b95ebf454645d7..7f34f49c9545b48c5206a1677a0c9a3e10164b11 100644 (file)
@@ -1,8 +1,8 @@
 ## @file
 # This file is used to parse meta files
 #
-# Copyright (c) 2008 - 2010, Intel Corporation
-# All rights reserved. This program and the accompanying materials
+# 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
@@ -82,6 +82,7 @@ class MetaFileParser(object):
         self.MetaFile = FilePath
         self._FileDir = os.path.dirname(self.MetaFile)
         self._Macros = copy.copy(Macros)
+        self._Macros["WORKSPACE"] = os.environ["WORKSPACE"]
 
         # for recursive parsing
         self._Owner = Owner
@@ -473,11 +474,11 @@ class InfParser(MetaFileParser):
     def _DefineParser(self):
         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
         self._ValueList[0:len(TokenList)] = TokenList
-        self._Macros[TokenList[0]] = ReplaceMacro(TokenList[1], self._Macros, False)
         if self._ValueList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
                             ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-
+        self._Macros[TokenList[0]] = ReplaceMacro(TokenList[1], self._Macros, False)
+        
     ## [nmake] section parser (R8.x style only)
     def _NmakeParser(self):
         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
@@ -490,13 +491,25 @@ class InfParser(MetaFileParser):
     ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
     def _PcdParser(self):
         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
-        self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
+        ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
+        if len(ValueList) != 2:
+            EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
+                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
+                            File=self.MetaFile, Line=self._LineIndex+1)
+        self._ValueList[0:1] = ValueList
         if len(TokenList) > 1:
             self._ValueList[2] = TokenList[1]
         if self._ValueList[0] == '' or self._ValueList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
                             File=self.MetaFile, Line=self._LineIndex+1)
+        # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
+        if self._ValueList[2] != '':
+            InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
+            if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
+                self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
+            elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
+                self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
 
     ## [depex] section parser
     def _DepexParser(self):
@@ -564,6 +577,7 @@ class DscParser(MetaFileParser):
 
     # sections which allow "!include" directive
     _IncludeAllowedSection = [
+        TAB_COMMON_DEFINES.upper(),
         TAB_LIBRARIES.upper(),
         TAB_LIBRARY_CLASSES.upper(),
         TAB_SKUIDS.upper(),
@@ -648,9 +662,37 @@ class DscParser(MetaFileParser):
                 continue
             # file private macros
             elif Line.upper().startswith('DEFINE '):
-                self._MacroParser()
+                if self._Enabled < 0:
+                    # Do not parse the macro and add it to self._Macros dictionary if directives
+                    # statement is evaluated to false.
+                    continue
+                
+                (Name, Value) = self._MacroParser()
+                # Make the defined macro in DSC [Defines] section also
+                # available for FDF file.
+                if self._SectionName == TAB_COMMON_DEFINES.upper():
+                    self._LastItem = self._Store(
+                    MODEL_META_DATA_GLOBAL_DEFINE,
+                    Name,
+                    Value,
+                    '',
+                    'COMMON',
+                    'COMMON',
+                    self._Owner,
+                    self._From,
+                    self._LineIndex+1,
+                    -1,
+                    self._LineIndex+1,
+                    -1,
+                    self._Enabled
+                    )
                 continue
             elif Line.upper().startswith('EDK_GLOBAL '):
+                if self._Enabled < 0:
+                    # Do not parse the macro and add it to self._Macros dictionary
+                    # if previous directives statement is evaluated to false.
+                    continue
+                
                 (Name, Value) = self._MacroParser()
                 for Arch, ModuleType in self._Scope:
                     self._LastItem = self._Store(
@@ -715,6 +757,22 @@ class DscParser(MetaFileParser):
         if TokenList[0] in ['FLASH_DEFINITION', 'OUTPUT_DIRECTORY']:
             TokenList[1] = NormPath(TokenList[1], self._Macros)
         self._ValueList[0:len(TokenList)] = TokenList
+        # Treat elements in the [defines] section as global macros for FDF file.
+        self._LastItem = self._Store(
+                            MODEL_META_DATA_GLOBAL_DEFINE,
+                            TokenList[0],
+                            TokenList[1],
+                            '',
+                            'COMMON',
+                            'COMMON',
+                            self._Owner,
+                            self._From,
+                            self._LineIndex+1,
+                            -1,
+                            self._LineIndex+1,
+                            -1,
+                            self._Enabled
+                            )
 
     ## <subsection_header> parser
     def _SubsectionHeaderParser(self):
@@ -761,8 +819,8 @@ class DscParser(MetaFileParser):
             if not self._SectionName in self._IncludeAllowedSection:
                 EdkLogger.error("Parser", FORMAT_INVALID, File=self.MetaFile, Line=self._LineIndex+1,
                                 ExtraData="'!include' is not allowed under section [%s]" % self._SectionName)
-            # the included file must be relative to the parsing file
-            IncludedFile = os.path.join(self._FileDir, self._ValueList[1])
+            # the included file must be relative to workspace
+            IncludedFile = os.path.join(os.environ["WORKSPACE"], NormPath(self._ValueList[1], self._Macros))
             Parser = DscParser(IncludedFile, self._FileType, self._Table, self._Macros, From=self._LastItem)
             # set the parser status with current status
             Parser._SectionName = self._SectionName
@@ -774,11 +832,14 @@ class DscParser(MetaFileParser):
             except:
                 EdkLogger.error("Parser", PARSER_ERROR, File=self.MetaFile, Line=self._LineIndex+1,
                                 ExtraData="Failed to parse content in file %s" % IncludedFile)
+            # insert an imaginary token in the DSC table to indicate its external dependency on another file
+            self._Store(MODEL_EXTERNAL_DEPENDENCY, IncludedFile, str(os.stat(IncludedFile)[8]), "")
             # update current status with sub-parser's status
             self._SectionName = Parser._SectionName
             self._SectionType = Parser._SectionType
             self._Scope       = Parser._Scope
             self._Enabled     = Parser._Enabled
+            self._Macros.update(Parser._Macros)
         else:
             if DirectiveName in ["!IF", "!IFDEF", "!IFNDEF"]:
                 # evaluate the expression
@@ -875,7 +936,13 @@ class DscParser(MetaFileParser):
             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
                             File=self.MetaFile, Line=self._LineIndex+1)
-
+        # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
+        DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
+        if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
+            self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
+        elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
+            self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
+            
     ## [components] section parser
     def _ComponentParser(self):
         if self._CurrentLine[-1] == '{':
@@ -963,6 +1030,7 @@ class DecParser(MetaFileParser):
     #
     def __init__(self, FilePath, FileType, Table, Macro=None):
         MetaFileParser.__init__(self, FilePath, FileType, Table, Macro, -1)
+        self._Comments = []
 
     ## Parser starter
     def Start(self):
@@ -973,27 +1041,34 @@ class DecParser(MetaFileParser):
             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
 
         for Index in range(0, len(self._Content)):
-            Line = CleanString(self._Content[Index])
+            Line, Comment = CleanString2(self._Content[Index])
+            self._CurrentLine = Line
+            self._LineIndex = Index
+
+            # save comment for later use
+            if Comment:
+                self._Comments.append((Comment, self._LineIndex+1))
             # skip empty line
             if Line == '':
                 continue
-            self._CurrentLine = Line
-            self._LineIndex = Index
 
             # section header
             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
                 self._SectionHeaderParser()
+                self._Comments = []
                 continue
             elif Line.startswith('DEFINE '):
                 self._MacroParser()
                 continue
             elif len(self._SectionType) == 0:
+                self._Comments = []
                 continue
 
             # section content
             self._ValueList = ['','','']
             self._SectionParser[self._SectionType[0]](self)
             if self._ValueList == None:
+                self._Comments = []
                 continue
 
             #
@@ -1015,6 +1090,22 @@ class DecParser(MetaFileParser):
                     -1,
                     0
                     )
+                for Comment, LineNo in self._Comments:
+                    self._Store(
+                        MODEL_META_DATA_COMMENT,
+                        Comment,
+                        self._ValueList[0],
+                        self._ValueList[1],
+                        Arch,
+                        ModuleType,
+                        self._LastItem,
+                        LineNo,
+                        -1,
+                        LineNo,
+                        -1,
+                        0
+                        )
+            self._Comments = []
         self._Done()
 
     ## Section header parser
@@ -1118,7 +1209,19 @@ class DecParser(MetaFileParser):
                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
                             File=self.MetaFile, Line=self._LineIndex+1)
 
-        ValueList = GetSplitValueList(TokenList[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",
@@ -1148,6 +1251,10 @@ class DecParser(MetaFileParser):
         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()