## @file
# This file is used to parse meta files
#
-# Copyright (c) 2008, 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
# 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 From ID from which the data comes (for !INCLUDE directive)
#
def __init__(self, FilePath, FileType, Table, Macros=None, Owner=-1, From=-1):
+ # prevent re-initialization
+ if hasattr(self, "_Table"):
+ return
self._Table = Table
self._FileType = FileType
self.MetaFile = FilePath
-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
continue
self._CurrentLine = Line
self._LineIndex = Index
-
+ if self._InSubsection and self._Owner == -1:
+ self._Owner = self._LastItem
+
# section header
if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
self._SectionHeaderParser()
if self._InSubsection:
SectionType = self._SubsectionType
SectionName = self._SubsectionName
- if self._Owner == -1:
- self._Owner = self._LastItem
else:
SectionType = self._SectionType
SectionName = self._SectionName
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
else:
self._Enabled = len(self._Eval)
- ## Evaludate the value of expression in "if/ifdef/ifndef" directives
+ ## Evaluate the Token for its value; for now only macros are supported.
+ def _EvaluateToken(self, TokenName, Expression):
+ if TokenName.startswith("$(") and TokenName.endswith(")"):
+ Name = TokenName[2:-1]
+ return self._Macros.get(Name)
+ else:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Unknown operand '%(Token)s', "
+ "please use '$(%(Token)s)' if '%(Token)s' is a macro" % {"Token" : TokenName},
+ File=self.MetaFile, Line=self._LineIndex+1, ExtraData=Expression)
+
+ ## Evaluate the value of expression in "if/ifdef/ifndef" directives
def _Evaluate(self, Expression):
TokenList = Expression.split()
TokenNumber = len(TokenList)
# one operand, guess it's just a macro name
if TokenNumber == 1:
- return TokenList[0] in self._Macros
+ TokenValue = self._EvaluateToken(TokenList[0], Expression)
+ return TokenValue != None
# two operands, suppose it's "!xxx" format
elif TokenNumber == 2:
Op = TokenList[0]
return self._OP_[Op](Value)
# three operands
elif TokenNumber == 3:
- Name = TokenList[0]
- if Name not in self._Macros:
+ TokenValue = self._EvaluateToken(TokenList[0], Expression)
+ if TokenValue == None:
return False
Value = TokenList[2]
if Value[0] in ["'", '"'] and Value[-1] in ["'", '"']:
if Op not in self._OP_:
EdkLogger.error('Parser', FORMAT_INVALID, "Unsupported operator [%s]" % Op, File=self.MetaFile,
Line=self._LineIndex+1, ExtraData=Expression)
- return self._OP_[Op](self._Macros[Name], Value)
+ return self._OP_[Op](TokenValue, Value)
else:
EdkLogger.error('Parser', FORMAT_INVALID, File=self.MetaFile, Line=self._LineIndex+1,
ExtraData=Expression)