summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python/UPT/Library
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/Python/UPT/Library')
-rw-r--r--BaseTools/Source/Python/UPT/Library/CommentGenerating.py149
-rw-r--r--BaseTools/Source/Python/UPT/Library/CommentParsing.py226
-rw-r--r--BaseTools/Source/Python/UPT/Library/DataType.py59
-rw-r--r--BaseTools/Source/Python/UPT/Library/ExpressionValidate.py167
-rw-r--r--BaseTools/Source/Python/UPT/Library/GlobalData.py13
-rw-r--r--BaseTools/Source/Python/UPT/Library/Misc.py210
-rw-r--r--BaseTools/Source/Python/UPT/Library/ParserValidate.py8
-rw-r--r--BaseTools/Source/Python/UPT/Library/Parsing.py115
-rw-r--r--BaseTools/Source/Python/UPT/Library/String.py174
-rw-r--r--BaseTools/Source/Python/UPT/Library/UniClassObject.py1042
-rw-r--r--BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py5
11 files changed, 1826 insertions, 342 deletions
diff --git a/BaseTools/Source/Python/UPT/Library/CommentGenerating.py b/BaseTools/Source/Python/UPT/Library/CommentGenerating.py
index 06da61b3e9..1cf919a96b 100644
--- a/BaseTools/Source/Python/UPT/Library/CommentGenerating.py
+++ b/BaseTools/Source/Python/UPT/Library/CommentGenerating.py
@@ -1,7 +1,7 @@
## @file
# This file is used to define comment generating interface
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -24,8 +24,18 @@ from Library.DataType import TAB_SPACE_SPLIT
from Library.DataType import TAB_INF_GUIDTYPE_VAR
from Library.DataType import USAGE_ITEM_NOTIFY
from Library.DataType import ITEM_UNDEFINED
-from Library.DataType import LANGUAGE_EN_US
-
+from Library.DataType import TAB_HEADER_COMMENT
+from Library.DataType import TAB_BINARY_HEADER_COMMENT
+from Library.DataType import TAB_COMMENT_SPLIT
+from Library.DataType import TAB_SPECIAL_COMMENT
+from Library.DataType import END_OF_LINE
+from Library.DataType import TAB_COMMENT_EDK1_SPLIT
+from Library.DataType import TAB_COMMENT_EDK1_START
+from Library.DataType import TAB_COMMENT_EDK1_END
+from Library.DataType import TAB_STAR
+from Library.DataType import TAB_PCD_PROMPT
+from Library.UniClassObject import ConvertSpecialUnicodes
+from Library.Misc import GetLocalValue
## GenTailCommentLines
#
# @param TailCommentLines: the tail comment lines that need to be generated
@@ -33,11 +43,11 @@ from Library.DataType import LANGUAGE_EN_US
# line tail comment
#
def GenTailCommentLines (TailCommentLines, LeadingSpaceNum = 0):
- EndOfLine = "\n"
- TailCommentLines = TailCommentLines.rstrip(EndOfLine)
- CommentStr = " ## " + (EndOfLine + LeadingSpaceNum * TAB_SPACE_SPLIT + \
- " ## ").join(GetSplitValueList(TailCommentLines, \
- EndOfLine))
+ TailCommentLines = TailCommentLines.rstrip(END_OF_LINE)
+ CommentStr = TAB_SPACE_SPLIT*2 + TAB_SPECIAL_COMMENT + TAB_SPACE_SPLIT + \
+ (END_OF_LINE + LeadingSpaceNum * TAB_SPACE_SPLIT + TAB_SPACE_SPLIT*2 + TAB_SPECIAL_COMMENT + \
+ TAB_SPACE_SPLIT).join(GetSplitValueList(TailCommentLines, END_OF_LINE))
+
return CommentStr
## GenGenericComment
@@ -47,10 +57,9 @@ def GenTailCommentLines (TailCommentLines, LeadingSpaceNum = 0):
def GenGenericComment (CommentLines):
if not CommentLines:
return ''
- EndOfLine = "\n"
- CommentLines = CommentLines.rstrip(EndOfLine)
- CommentStr = '## ' + (EndOfLine + '# ').join\
- (GetSplitValueList(CommentLines, EndOfLine)) + EndOfLine
+ CommentLines = CommentLines.rstrip(END_OF_LINE)
+ CommentStr = TAB_SPECIAL_COMMENT + TAB_SPACE_SPLIT + (END_OF_LINE + TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT).join\
+ (GetSplitValueList(CommentLines, END_OF_LINE)) + END_OF_LINE
return CommentStr
## GenGenericCommentF
@@ -61,23 +70,40 @@ def GenGenericComment (CommentLines):
# @param CommentLines: Generic comment Text, maybe Multiple Lines
# @return CommentStr: Generated comment line
#
-def GenGenericCommentF (CommentLines, NumOfPound=1):
+def GenGenericCommentF (CommentLines, NumOfPound=1, IsPrompt=False, IsInfLibraryClass=False):
if not CommentLines:
return ''
- EndOfLine = "\n"
#
# if comment end with '\n', then remove it to prevent one extra line
# generate later on
#
- if CommentLines.endswith(EndOfLine):
+ if CommentLines.endswith(END_OF_LINE):
CommentLines = CommentLines[:-1]
- CommentLineList = GetSplitValueList(CommentLines, EndOfLine)
CommentStr = ''
- for Line in CommentLineList:
- if Line == '':
- CommentStr += '#' * NumOfPound + '\n'
- else:
- CommentStr += '#' * NumOfPound + ' ' + Line + '\n'
+ if IsPrompt:
+ CommentStr += TAB_COMMENT_SPLIT * NumOfPound + TAB_SPACE_SPLIT + TAB_PCD_PROMPT + TAB_SPACE_SPLIT + \
+ CommentLines.replace(END_OF_LINE, '') + END_OF_LINE
+ else:
+ CommentLineList = GetSplitValueList(CommentLines, END_OF_LINE)
+ FindLibraryClass = False
+ for Line in CommentLineList:
+ # If this comment is for @libraryclass and it has multiple lines
+ # make sure the second lines align to the first line after @libraryclass as below
+ #
+ # ## @libraryclass XYZ FIRST_LINE
+ # ## ABC SECOND_LINE
+ #
+ if IsInfLibraryClass and Line.find(u'@libraryclass ') > -1:
+ FindLibraryClass = True
+ if Line == '':
+ CommentStr += TAB_COMMENT_SPLIT * NumOfPound + END_OF_LINE
+ else:
+ if FindLibraryClass and Line.find(u'@libraryclass ') > -1:
+ CommentStr += TAB_COMMENT_SPLIT * NumOfPound + TAB_SPACE_SPLIT + Line + END_OF_LINE
+ elif FindLibraryClass:
+ CommentStr += TAB_COMMENT_SPLIT * NumOfPound + TAB_SPACE_SPLIT * 16 + Line + END_OF_LINE
+ else:
+ CommentStr += TAB_COMMENT_SPLIT * NumOfPound + TAB_SPACE_SPLIT + Line + END_OF_LINE
return CommentStr
@@ -91,40 +117,57 @@ def GenGenericCommentF (CommentLines, NumOfPound=1):
# @param Copyright possible multiple copyright lines
# @param License possible multiple license lines
#
-def GenHeaderCommentSection(Abstract, Description, Copyright, License):
- EndOfLine = '\n'
+def GenHeaderCommentSection(Abstract, Description, Copyright, License, IsBinaryHeader=False, \
+ CommChar=TAB_COMMENT_SPLIT):
Content = ''
-
- Content += '## @file' + EndOfLine
+
+ #
+ # Convert special character to (c), (r) and (tm).
+ #
+ if isinstance(Abstract, unicode):
+ Abstract = ConvertSpecialUnicodes(Abstract)
+ if isinstance(Description, unicode):
+ Description = ConvertSpecialUnicodes(Description)
+ if IsBinaryHeader:
+ Content += CommChar * 2 + TAB_SPACE_SPLIT + TAB_BINARY_HEADER_COMMENT + END_OF_LINE
+ elif CommChar == TAB_COMMENT_EDK1_SPLIT:
+ Content += CommChar + TAB_SPACE_SPLIT + TAB_COMMENT_EDK1_START + TAB_STAR + TAB_SPACE_SPLIT +\
+ TAB_HEADER_COMMENT + END_OF_LINE
+ else:
+ Content += CommChar * 2 + TAB_SPACE_SPLIT + TAB_HEADER_COMMENT + END_OF_LINE
if Abstract:
- Abstract = Abstract.rstrip(EndOfLine)
- Content += '# ' + Abstract + EndOfLine
- Content += '#' + EndOfLine
+ Abstract = Abstract.rstrip(END_OF_LINE)
+ Content += CommChar + TAB_SPACE_SPLIT + (END_OF_LINE + CommChar + TAB_SPACE_SPLIT).join(GetSplitValueList\
+ (Abstract, END_OF_LINE))
+ Content += END_OF_LINE + CommChar + END_OF_LINE
else:
- Content += '#' + EndOfLine
+ Content += CommChar + END_OF_LINE
if Description:
- Description = Description.rstrip(EndOfLine)
- Content += '# ' + (EndOfLine + '# ').join(GetSplitValueList\
- (Description, '\n'))
- Content += EndOfLine + '#' + EndOfLine
+ Description = Description.rstrip(END_OF_LINE)
+ Content += CommChar + TAB_SPACE_SPLIT + (END_OF_LINE + CommChar + TAB_SPACE_SPLIT).join(GetSplitValueList\
+ (Description, END_OF_LINE))
+ Content += END_OF_LINE + CommChar + END_OF_LINE
#
# There is no '#\n' line to separate multiple copyright lines in code base
#
if Copyright:
- Copyright = Copyright.rstrip(EndOfLine)
- Content += '# ' + (EndOfLine + '# ').join\
- (GetSplitValueList(Copyright, '\n'))
- Content += EndOfLine + '#' + EndOfLine
+ Copyright = Copyright.rstrip(END_OF_LINE)
+ Content += CommChar + TAB_SPACE_SPLIT + (END_OF_LINE + CommChar + TAB_SPACE_SPLIT).join\
+ (GetSplitValueList(Copyright, END_OF_LINE))
+ Content += END_OF_LINE + CommChar + END_OF_LINE
if License:
- License = License.rstrip(EndOfLine)
- Content += '# ' + (EndOfLine + '# ').join(GetSplitValueList\
- (License, '\n'))
- Content += EndOfLine + '#' + EndOfLine
-
- Content += '##' + EndOfLine
+ License = License.rstrip(END_OF_LINE)
+ Content += CommChar + TAB_SPACE_SPLIT + (END_OF_LINE + CommChar + TAB_SPACE_SPLIT).join(GetSplitValueList\
+ (License, END_OF_LINE))
+ Content += END_OF_LINE + CommChar + END_OF_LINE
+
+ if CommChar == TAB_COMMENT_EDK1_SPLIT:
+ Content += CommChar + TAB_SPACE_SPLIT + TAB_STAR + TAB_COMMENT_EDK1_END + END_OF_LINE
+ else:
+ Content += CommChar * 2 + END_OF_LINE
return Content
@@ -197,21 +240,7 @@ def GenDecTailComment (SupModuleList):
# @return HelpStr: the help text string found, '' means no help text found
#
def _GetHelpStr(HelpTextObjList):
- HelpStr = ''
-
- for HelpObj in HelpTextObjList:
- if HelpObj and HelpObj.GetLang() == LANGUAGE_EN_US:
- HelpStr = HelpObj.GetString()
- return HelpStr
-
- for HelpObj in HelpTextObjList:
- if HelpObj and HelpObj.GetLang().startswith('en'):
- HelpStr = HelpObj.GetString()
- return HelpStr
-
+ ValueList = []
for HelpObj in HelpTextObjList:
- if HelpObj and not HelpObj.GetLang():
- HelpStr = HelpObj.GetString()
- return HelpStr
-
- return HelpStr \ No newline at end of file
+ ValueList.append((HelpObj.GetLang(), HelpObj.GetString()))
+ return GetLocalValue(ValueList, True)
diff --git a/BaseTools/Source/Python/UPT/Library/CommentParsing.py b/BaseTools/Source/Python/UPT/Library/CommentParsing.py
index 5c07f34a74..e6d45103f9 100644
--- a/BaseTools/Source/Python/UPT/Library/CommentParsing.py
+++ b/BaseTools/Source/Python/UPT/Library/CommentParsing.py
@@ -1,7 +1,7 @@
## @file
# This file is used to define comment parsing interface
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -32,6 +32,17 @@ from Library.DataType import HEADER_COMMENT_DESCRIPTION
from Library.DataType import TAB_SPACE_SPLIT
from Library.DataType import TAB_COMMA_SPLIT
from Library.DataType import SUP_MODULE_LIST
+from Library.DataType import TAB_VALUE_SPLIT
+from Library.DataType import TAB_PCD_VALIDRANGE
+from Library.DataType import TAB_PCD_VALIDLIST
+from Library.DataType import TAB_PCD_EXPRESSION
+from Library.DataType import TAB_PCD_PROMPT
+from Library.DataType import TAB_CAPHEX_START
+from Library.DataType import TAB_HEX_START
+from Library.DataType import PCD_ERR_CODE_MAX_SIZE
+from Library.ExpressionValidate import IsValidRangeExpr
+from Library.ExpressionValidate import IsValidListExpr
+from Library.ExpressionValidate import IsValidLogicalExpr
from Object.POM.CommonObject import TextObject
from Object.POM.CommonObject import PcdErrorObject
import Logger.Log as Logger
@@ -47,13 +58,16 @@ from Logger import StringTable as ST
# @param CommentList: List of (Comment, LineNumber)
# @param FileName: FileName of the comment
#
-def ParseHeaderCommentSection(CommentList, FileName = None):
+def ParseHeaderCommentSection(CommentList, FileName = None, IsBinaryHeader = False):
Abstract = ''
Description = ''
Copyright = ''
License = ''
EndOfLine = "\n"
- STR_HEADER_COMMENT_START = "@file"
+ if IsBinaryHeader:
+ STR_HEADER_COMMENT_START = "@BinaryHeader"
+ else:
+ STR_HEADER_COMMENT_START = "@file"
HeaderCommentStage = HEADER_COMMENT_NOT_STARTED
#
@@ -94,7 +108,6 @@ def ParseHeaderCommentSection(CommentList, FileName = None):
# in case there is no abstract and description
#
if not Comment:
- Abstract = ''
HeaderCommentStage = HEADER_COMMENT_DESCRIPTION
elif _IsCopyrightLine(Comment):
Result, ErrMsg = _ValidateCopyright(Comment)
@@ -134,14 +147,7 @@ def ParseHeaderCommentSection(CommentList, FileName = None):
if not Comment and not License:
continue
License += Comment + EndOfLine
-
- if not Copyright:
- Logger.Error("\nUPT", FORMAT_INVALID, ST.ERR_COPYRIGHT_MISSING, \
- FileName)
-
- if not License:
- Logger.Error("\nUPT", FORMAT_INVALID, ST.ERR_LICENSE_MISSING, FileName)
-
+
return Abstract.strip(), Description.strip(), Copyright.strip(), License.strip()
## _IsCopyrightLine
@@ -158,7 +164,7 @@ def _IsCopyrightLine (LineContent):
ReIsCopyrightRe = re.compile(r"""(^|\s)COPYRIGHT *\(""", re.DOTALL)
if ReIsCopyrightRe.search(LineContent):
Result = True
-
+
return Result
## ParseGenericComment
@@ -188,6 +194,37 @@ def ParseGenericComment (GenericComment, ContainerFile=None, SkipTag=None):
return HelpTxt
+## ParsePcdErrorCode
+#
+# @param Value: original ErrorCode value
+# @param ContainerFile: Input value for filename of Dec file
+# @param LineNum: Line Num
+#
+def ParsePcdErrorCode (Value = None, ContainerFile = None, LineNum = None):
+ try:
+ if Value.strip().startswith((TAB_HEX_START, TAB_CAPHEX_START)):
+ Base = 16
+ else:
+ Base = 10
+ ErrorCode = long(Value, Base)
+ if ErrorCode > PCD_ERR_CODE_MAX_SIZE or ErrorCode < 0:
+ Logger.Error('Parser',
+ FORMAT_NOT_SUPPORTED,
+ "The format %s of ErrorCode is not valid, should be UNIT32 type or long type" % Value,
+ File = ContainerFile,
+ Line = LineNum)
+ #
+ # To delete the tailing 'L'
+ #
+ return hex(ErrorCode)[:-1]
+ except ValueError, XStr:
+ if XStr:
+ pass
+ Logger.Error('Parser',
+ FORMAT_NOT_SUPPORTED,
+ "The format %s of ErrorCode is not valid, should be UNIT32 type or long type" % Value,
+ File = ContainerFile,
+ Line = LineNum)
## ParseDecPcdGenericComment
#
@@ -195,46 +232,135 @@ def ParseGenericComment (GenericComment, ContainerFile=None, SkipTag=None):
# LineNum)
# @param ContainerFile: Input value for filename of Dec file
#
-def ParseDecPcdGenericComment (GenericComment, ContainerFile):
+def ParseDecPcdGenericComment (GenericComment, ContainerFile, TokenSpaceGuidCName, CName, MacroReplaceDict):
HelpStr = ''
+ PromptStr = ''
PcdErr = None
+ PcdErrList = []
+ ValidValueNum = 0
+ ValidRangeNum = 0
+ ExpressionNum = 0
for (CommentLine, LineNum) in GenericComment:
Comment = CleanString2(CommentLine)[1]
- if Comment.startswith("@ValidRange"):
- if PcdErr:
+ #
+ # To replace Macro
+ #
+ MACRO_PATTERN = '[\t\s]*\$\([A-Z][_A-Z0-9]*\)'
+ MatchedStrs = re.findall(MACRO_PATTERN, Comment)
+ for MatchedStr in MatchedStrs:
+ if MatchedStr:
+ Macro = MatchedStr.strip().lstrip('$(').rstrip(')').strip()
+ if Macro in MacroReplaceDict:
+ Comment = Comment.replace(MatchedStr, MacroReplaceDict[Macro])
+ if Comment.startswith(TAB_PCD_VALIDRANGE):
+ if ValidValueNum > 0 or ExpressionNum > 0:
Logger.Error('Parser',
FORMAT_NOT_SUPPORTED,
ST.WRN_MULTI_PCD_RANGES,
File = ContainerFile,
Line = LineNum)
- ValidRange = Comment.replace("@ValidRange", "", 1)
- if _CheckRangeExpression(ValidRange):
+ else:
PcdErr = PcdErrorObject()
- PcdErr.SetValidValueRange(ValidRange)
- elif Comment.startswith("@ValidList"):
- if PcdErr:
+ PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)
+ PcdErr.SetCName(CName)
+ PcdErr.SetFileLine(Comment)
+ PcdErr.SetLineNum(LineNum)
+ ValidRangeNum += 1
+ ValidRange = Comment.replace(TAB_PCD_VALIDRANGE, "", 1).strip()
+ Valid, Cause = _CheckRangeExpression(ValidRange)
+ if Valid:
+ ValueList = ValidRange.split(TAB_VALUE_SPLIT)
+ if len(ValueList) > 1:
+ PcdErr.SetValidValueRange((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())
+ PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))
+ else:
+ PcdErr.SetValidValueRange(ValidRange)
+ PcdErrList.append(PcdErr)
+ else:
+ Logger.Error("Parser",
+ FORMAT_NOT_SUPPORTED,
+ Cause,
+ ContainerFile,
+ LineNum)
+ elif Comment.startswith(TAB_PCD_VALIDLIST):
+ if ValidRangeNum > 0 or ExpressionNum > 0:
Logger.Error('Parser',
FORMAT_NOT_SUPPORTED,
ST.WRN_MULTI_PCD_RANGES,
File = ContainerFile,
Line = LineNum)
- ValidValue = Comment.replace("@ValidList", "", 1).replace(TAB_COMMA_SPLIT, TAB_SPACE_SPLIT)
- PcdErr = PcdErrorObject()
- PcdErr.SetValidValue(ValidValue)
- elif Comment.startswith("@Expression"):
- if PcdErr:
+ elif ValidValueNum > 0:
+ Logger.Error('Parser',
+ FORMAT_NOT_SUPPORTED,
+ ST.WRN_MULTI_PCD_VALIDVALUE,
+ File = ContainerFile,
+ Line = LineNum)
+ else:
+ PcdErr = PcdErrorObject()
+ PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)
+ PcdErr.SetCName(CName)
+ PcdErr.SetFileLine(Comment)
+ PcdErr.SetLineNum(LineNum)
+ ValidValueNum += 1
+ ValidValueExpr = Comment.replace(TAB_PCD_VALIDLIST, "", 1).strip()
+ Valid, Cause = _CheckListExpression(ValidValueExpr)
+ if Valid:
+ ValidValue = Comment.replace(TAB_PCD_VALIDLIST, "", 1).replace(TAB_COMMA_SPLIT, TAB_SPACE_SPLIT)
+ ValueList = ValidValue.split(TAB_VALUE_SPLIT)
+ if len(ValueList) > 1:
+ PcdErr.SetValidValue((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())
+ PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))
+ else:
+ PcdErr.SetValidValue(ValidValue)
+ PcdErrList.append(PcdErr)
+ else:
+ Logger.Error("Parser",
+ FORMAT_NOT_SUPPORTED,
+ Cause,
+ ContainerFile,
+ LineNum)
+ elif Comment.startswith(TAB_PCD_EXPRESSION):
+ if ValidRangeNum > 0 or ValidValueNum > 0:
Logger.Error('Parser',
FORMAT_NOT_SUPPORTED,
ST.WRN_MULTI_PCD_RANGES,
File = ContainerFile,
Line = LineNum)
- Expression = Comment.replace("@Expression", "", 1)
- if _CheckRangeExpression(Expression):
+ else:
PcdErr = PcdErrorObject()
- PcdErr.SetExpression(Expression)
+ PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)
+ PcdErr.SetCName(CName)
+ PcdErr.SetFileLine(Comment)
+ PcdErr.SetLineNum(LineNum)
+ ExpressionNum += 1
+ Expression = Comment.replace(TAB_PCD_EXPRESSION, "", 1).strip()
+ Valid, Cause = _CheckExpression(Expression)
+ if Valid:
+ ValueList = Expression.split(TAB_VALUE_SPLIT)
+ if len(ValueList) > 1:
+ PcdErr.SetExpression((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())
+ PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))
+ else:
+ PcdErr.SetExpression(Expression)
+ PcdErrList.append(PcdErr)
+ else:
+ Logger.Error("Parser",
+ FORMAT_NOT_SUPPORTED,
+ Cause,
+ ContainerFile,
+ LineNum)
+ elif Comment.startswith(TAB_PCD_PROMPT):
+ if PromptStr:
+ Logger.Error('Parser',
+ FORMAT_NOT_SUPPORTED,
+ ST.WRN_MULTI_PCD_PROMPT,
+ File = ContainerFile,
+ Line = LineNum)
+ PromptStr = Comment.replace(TAB_PCD_PROMPT, "", 1).strip()
else:
- HelpStr += Comment + '\n'
+ if Comment:
+ HelpStr += Comment + '\n'
#
# remove the last EOL if the comment is of format 'FOO\n'
@@ -243,7 +369,7 @@ def ParseDecPcdGenericComment (GenericComment, ContainerFile):
if HelpStr != '\n' and not HelpStr.endswith('\n\n'):
HelpStr = HelpStr[:-1]
- return HelpStr, PcdErr
+ return HelpStr, PcdErrList, PromptStr
## ParseDecPcdTailComment
#
@@ -289,18 +415,43 @@ def ParseDecPcdTailComment (TailCommentList, ContainerFile):
return SupModuleList, HelpStr
+## _CheckListExpression
+#
+# @param Expression: Pcd value list expression
+#
+def _CheckListExpression(Expression):
+ ListExpr = ''
+ if TAB_VALUE_SPLIT in Expression:
+ ListExpr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]
+ else:
+ ListExpr = Expression
+
+ return IsValidListExpr(ListExpr)
+
+## _CheckExpreesion
+#
+# @param Expression: Pcd value expression
+#
+def _CheckExpression(Expression):
+ Expr = ''
+ if TAB_VALUE_SPLIT in Expression:
+ Expr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]
+ else:
+ Expr = Expression
+ return IsValidLogicalExpr(Expr, True)
## _CheckRangeExpression
#
# @param Expression: Pcd range expression
#
def _CheckRangeExpression(Expression):
- #
- # check grammar for Pcd range expression is not required yet
- #
- if Expression:
- pass
- return True
+ RangeExpr = ''
+ if TAB_VALUE_SPLIT in Expression:
+ RangeExpr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]
+ else:
+ RangeExpr = Expression
+
+ return IsValidRangeExpr(RangeExpr)
## ValidateCopyright
#
@@ -349,7 +500,6 @@ def ParseComment (Comment, UsageTokens, TypeTokens, RemoveTokens, ParseVariable)
Usage = None
Type = None
String = None
- HelpText = None
Comment = Comment[0]
diff --git a/BaseTools/Source/Python/UPT/Library/DataType.py b/BaseTools/Source/Python/UPT/Library/DataType.py
index 4b30f3343e..8449dc8d6d 100644
--- a/BaseTools/Source/Python/UPT/Library/DataType.py
+++ b/BaseTools/Source/Python/UPT/Library/DataType.py
@@ -1,7 +1,7 @@
## @file
# This file is used to define class for data type structure
#
-# Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -47,7 +47,10 @@ USAGE_LIST = ["CONSUMES",
"PRODUCES",
"SOMETIMES_PRODUCES"]
-LANGUAGE_EN_US = 'en-US'
+TAB_LANGUAGE_EN_US = 'en-US'
+TAB_LANGUAGE_ENG = 'eng'
+TAB_LANGUAGE_EN = 'en'
+TAB_LANGUAGE_EN_X = 'en-x-tianocore'
USAGE_ITEM_PRODUCES = 'PRODUCES'
USAGE_ITEM_SOMETIMES_PRODUCES = 'SOMETIMES_PRODUCES'
@@ -80,6 +83,14 @@ USAGE_SOMETIMES_CONSUMES_LIST = [USAGE_ITEM_SOMETIMES_CONSUMES,
ITEM_UNDEFINED = 'UNDEFINED'
+TAB_PCD_VALIDRANGE = '@ValidRange'
+TAB_PCD_VALIDLIST = '@ValidList'
+TAB_PCD_EXPRESSION = '@Expression'
+TAB_PCD_PROMPT = '@Prompt'
+TAB_STR_TOKENCNAME = 'STR'
+TAB_STR_TOKENPROMPT = 'PROMPT'
+TAB_STR_TOKENHELP = 'HELP'
+TAB_STR_TOKENERR = 'ERR'
#
# Dictionary of usage tokens and their synonmys
@@ -269,11 +280,12 @@ PCD_USAGE_TYPE_LIST_OF_UPT = PCD_USAGE_TYPE_LIST_OF_MODULE
##
# Binary File Type List
#
-BINARY_FILE_TYPE_LIST = ["GUID", "PE32", "PIC", "TE", "DXE_DEPEX", "VER", "UI", "COMPAT16", "FV", "BIN", "RAW",
+BINARY_FILE_TYPE_LIST = ["PE32", "PIC", "TE", "DXE_DEPEX", "VER", "UI", "COMPAT16", "FV", "BIN", "RAW",
"ACPI", "ASL",
"PEI_DEPEX",
"SMM_DEPEX",
- "SUBTYPE_GUID"
+ "SUBTYPE_GUID",
+ "DISPOSABLE"
]
BINARY_FILE_TYPE_LIST_IN_UDP = \
["GUID", "FREEFORM",
@@ -285,6 +297,7 @@ BINARY_FILE_TYPE_LIST_IN_UDP = \
"BIN", "VER", "UI"
]
+SUBTYPE_GUID_BINARY_FILE_TYPE = "FREEFORM"
##
# Possible values for COMPONENT_TYPE, and their descriptions, are listed in
# the table,
@@ -328,6 +341,7 @@ TAB_EQUAL_SPLIT = '='
TAB_DEQUAL_SPLIT = '=='
TAB_VALUE_SPLIT = '|'
TAB_COMMA_SPLIT = ','
+TAB_HORIZON_LINE_SPLIT = '-'
TAB_SPACE_SPLIT = ' '
TAB_UNDERLINE_SPLIT = '_'
TAB_SEMI_COLON_SPLIT = ';'
@@ -341,7 +355,13 @@ TAB_BACK_SLASH = '/'
TAB_SPECIAL_COMMENT = '##'
TAB_HEADER_COMMENT = '@file'
TAB_BINARY_HEADER_COMMENT = '@BinaryHeader'
-TAB_STAR = "*"
+TAB_STAR = '*'
+TAB_ENCODING_UTF16LE = 'utf_16_le'
+TAB_CAPHEX_START = '0X'
+TAB_HEX_START = '0x'
+TAB_PCD_ERROR = 'Error'
+TAB_PCD_ERROR_SECTION_COMMENT = 'Error message section'
+TAB_UNI_FILE_SUFFIXS = ['.uni', '.UNI', '.Uni']
TAB_EDK_SOURCE = '$(EDK_SOURCE)'
TAB_EFI_SOURCE = '$(EFI_SOURCE)'
@@ -354,10 +374,9 @@ TAB_ARCH_X64 = 'X64'
TAB_ARCH_IPF = 'IPF'
TAB_ARCH_ARM = 'ARM'
TAB_ARCH_EBC = 'EBC'
-TAB_ARCH_AARCH64 = 'AARCH64'
ARCH_LIST = \
-[TAB_ARCH_IA32, TAB_ARCH_X64, TAB_ARCH_IPF, TAB_ARCH_ARM, TAB_ARCH_EBC, TAB_ARCH_AARCH64]
+[TAB_ARCH_IA32, TAB_ARCH_X64, TAB_ARCH_IPF, TAB_ARCH_ARM, TAB_ARCH_EBC]
SUP_MODULE_BASE = 'BASE'
SUP_MODULE_SEC = 'SEC'
@@ -442,7 +461,6 @@ TAB_SOURCES_X64 = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_X64
TAB_SOURCES_IPF = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_IPF
TAB_SOURCES_ARM = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_ARM
TAB_SOURCES_EBC = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_EBC
-TAB_SOURCES_AARCH64 = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_BINARIES = 'Binaries'
TAB_BINARIES_COMMON = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_COMMON
@@ -451,7 +469,6 @@ TAB_BINARIES_X64 = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_X64
TAB_BINARIES_IPF = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_IPF
TAB_BINARIES_ARM = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_ARM
TAB_BINARIES_EBC = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_EBC
-TAB_BINARIES_AARCH64 = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_INCLUDES = 'Includes'
TAB_INCLUDES_COMMON = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_COMMON
@@ -460,7 +477,6 @@ TAB_INCLUDES_X64 = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_X64
TAB_INCLUDES_IPF = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_IPF
TAB_INCLUDES_ARM = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_ARM
TAB_INCLUDES_EBC = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_EBC
-TAB_INCLUDES_AARCH64 = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_GUIDS = 'Guids'
TAB_GUIDS_COMMON = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_COMMON
@@ -469,7 +485,6 @@ TAB_GUIDS_X64 = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_X64
TAB_GUIDS_IPF = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_IPF
TAB_GUIDS_ARM = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_ARM
TAB_GUIDS_EBC = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_EBC
-TAB_GUIDS_AARCH64 = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_PROTOCOLS = 'Protocols'
TAB_PROTOCOLS_COMMON = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_COMMON
@@ -478,7 +493,6 @@ TAB_PROTOCOLS_X64 = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_X64
TAB_PROTOCOLS_IPF = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_IPF
TAB_PROTOCOLS_ARM = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_ARM
TAB_PROTOCOLS_EBC = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_EBC
-TAB_PROTOCOLS_AARCH64 = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_PPIS = 'Ppis'
TAB_PPIS_COMMON = TAB_PPIS + TAB_SPLIT + TAB_ARCH_COMMON
@@ -487,7 +501,6 @@ TAB_PPIS_X64 = TAB_PPIS + TAB_SPLIT + TAB_ARCH_X64
TAB_PPIS_IPF = TAB_PPIS + TAB_SPLIT + TAB_ARCH_IPF
TAB_PPIS_ARM = TAB_PPIS + TAB_SPLIT + TAB_ARCH_ARM
TAB_PPIS_EBC = TAB_PPIS + TAB_SPLIT + TAB_ARCH_EBC
-TAB_PPIS_AARCH64 = TAB_PPIS + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_LIBRARY_CLASSES = 'LibraryClasses'
TAB_LIBRARY_CLASSES_COMMON = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_COMMON
@@ -496,7 +509,6 @@ TAB_LIBRARY_CLASSES_X64 = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_X64
TAB_LIBRARY_CLASSES_IPF = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_IPF
TAB_LIBRARY_CLASSES_ARM = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_ARM
TAB_LIBRARY_CLASSES_EBC = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_EBC
-TAB_LIBRARY_CLASSES_AARCH64 = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_PACKAGES = 'Packages'
TAB_PACKAGES_COMMON = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_COMMON
@@ -505,7 +517,6 @@ TAB_PACKAGES_X64 = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_X64
TAB_PACKAGES_IPF = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_IPF
TAB_PACKAGES_ARM = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_ARM
TAB_PACKAGES_EBC = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_EBC
-TAB_PACKAGES_AARCH64 = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_PCDS = 'Pcds'
TAB_PCDS_FIXED_AT_BUILD = 'FixedAtBuild'
@@ -545,8 +556,6 @@ TAB_PCDS_FIXED_AT_BUILD_ARM = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \
TAB_SPLIT + TAB_ARCH_ARM
TAB_PCDS_FIXED_AT_BUILD_EBC = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \
TAB_SPLIT + TAB_ARCH_EBC
-TAB_PCDS_FIXED_AT_BUILD_AARCH64 = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \
-TAB_SPLIT + TAB_ARCH_AARCH64
TAB_PCDS_PATCHABLE_IN_MODULE_NULL = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE
TAB_PCDS_PATCHABLE_IN_MODULE_COMMON = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE \
@@ -561,8 +570,6 @@ TAB_PCDS_PATCHABLE_IN_MODULE_ARM = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + \
TAB_SPLIT + TAB_ARCH_ARM
TAB_PCDS_PATCHABLE_IN_MODULE_EBC = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + \
TAB_SPLIT + TAB_ARCH_EBC
-TAB_PCDS_PATCHABLE_IN_MODULE_AARCH64 = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + \
-TAB_SPLIT + TAB_ARCH_AARCH64
TAB_PCDS_FEATURE_FLAG_NULL = TAB_PCDS + TAB_PCDS_FEATURE_FLAG
TAB_PCDS_FEATURE_FLAG_COMMON = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT \
@@ -577,8 +584,6 @@ TAB_PCDS_FEATURE_FLAG_ARM = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + \
TAB_ARCH_ARM
TAB_PCDS_FEATURE_FLAG_EBC = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + \
TAB_ARCH_EBC
-TAB_PCDS_FEATURE_FLAG_AARCH64 = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + \
-TAB_ARCH_AARCH64
TAB_PCDS_DYNAMIC_EX_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX
TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX_DEFAULT
@@ -596,8 +601,6 @@ TAB_PCDS_DYNAMIC_EX_ARM = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \
TAB_ARCH_ARM
TAB_PCDS_DYNAMIC_EX_EBC = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \
TAB_ARCH_EBC
-TAB_PCDS_DYNAMIC_EX_AARCH64 = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \
-TAB_ARCH_AARCH64
TAB_PCDS_DYNAMIC_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC
TAB_PCDS_DYNAMIC_DEFAULT_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_DEFAULT
@@ -610,7 +613,6 @@ TAB_PCDS_DYNAMIC_X64 = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_X64
TAB_PCDS_DYNAMIC_IPF = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_IPF
TAB_PCDS_DYNAMIC_ARM = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_ARM
TAB_PCDS_DYNAMIC_EBC = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_EBC
-TAB_PCDS_DYNAMIC_AARCH64 = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_PCD_DYNAMIC_TYPE_LIST = [TAB_PCDS_DYNAMIC_DEFAULT_NULL, \
TAB_PCDS_DYNAMIC_VPD_NULL, \
@@ -651,7 +653,6 @@ TAB_DEPEX_X64 = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_X64
TAB_DEPEX_IPF = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_IPF
TAB_DEPEX_ARM = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_ARM
TAB_DEPEX_EBC = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_EBC
-TAB_DEPEX_AARCH64 = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_SKUIDS = 'SkuIds'
@@ -662,7 +663,6 @@ TAB_LIBRARIES_X64 = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_X64
TAB_LIBRARIES_IPF = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_IPF
TAB_LIBRARIES_ARM = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_ARM
TAB_LIBRARIES_EBC = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_EBC
-TAB_LIBRARIES_AARCH64 = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_COMPONENTS = 'Components'
TAB_COMPONENTS_COMMON = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_COMMON
@@ -671,7 +671,6 @@ TAB_COMPONENTS_X64 = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_X64
TAB_COMPONENTS_IPF = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_IPF
TAB_COMPONENTS_ARM = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_ARM
TAB_COMPONENTS_EBC = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_EBC
-TAB_COMPONENTS_AARCH64 = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_AARCH64
TAB_COMPONENTS_SOURCE_OVERRIDE_PATH = 'SOURCE_OVERRIDE_PATH'
@@ -699,6 +698,7 @@ TAB_INF_DEFINES_EFI_SPECIFICATION_VERSION = 'EFI_SPECIFICATION_VERSION'
TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION = 'UEFI_SPECIFICATION_VERSION'
TAB_INF_DEFINES_PI_SPECIFICATION_VERSION = 'PI_SPECIFICATION_VERSION'
TAB_INF_DEFINES_EDK_RELEASE_VERSION = 'EDK_RELEASE_VERSION'
+TAB_INF_DEFINES_MODULE_UNI_FILE = 'MODULE_UNI_FILE'
TAB_INF_DEFINES_BINARY_MODULE = 'BINARY_MODULE'
TAB_INF_DEFINES_LIBRARY_CLASS = 'LIBRARY_CLASS'
TAB_INF_DEFINES_COMPONENT_TYPE = 'COMPONENT_TYPE'
@@ -750,7 +750,7 @@ TAB_DEC_DEFINES_DEC_SPECIFICATION = 'DEC_SPECIFICATION'
TAB_DEC_DEFINES_PACKAGE_NAME = 'PACKAGE_NAME'
TAB_DEC_DEFINES_PACKAGE_GUID = 'PACKAGE_GUID'
TAB_DEC_DEFINES_PACKAGE_VERSION = 'PACKAGE_VERSION'
-TAB_DEC_DEFINES_PKG_UNI_FILE = 'PKG_UNI_FILE'
+TAB_DEC_DEFINES_PKG_UNI_FILE = 'PACKAGE_UNI_FILE'
TAB_DEC_PACKAGE_ABSTRACT = 'STR_PACKAGE_ABSTRACT'
TAB_DEC_PACKAGE_DESCRIPTION = 'STR_PACKAGE_DESCRIPTION'
TAB_DEC_PACKAGE_LICENSE = 'STR_PACKAGE_LICENSE'
@@ -827,6 +827,7 @@ TAB_HEADER_COPYRIGHT = 'Copyright'
TAB_HEADER_LICENSE = 'License'
TAB_BINARY_HEADER_IDENTIFIER = 'BinaryHeader'
TAB_BINARY_HEADER_USERID = 'TianoCore'
+
#
# Build database path
#
@@ -951,3 +952,5 @@ TOOL_FAMILY_LIST = ["MSFT",
TYPE_HOB_SECTION = 'HOB'
TYPE_EVENT_SECTION = 'EVENT'
TYPE_BOOTMODE_SECTION = 'BOOTMODE'
+
+PCD_ERR_CODE_MAX_SIZE = 4294967295
diff --git a/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py b/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py
index 3b476b4c48..090c7eb957 100644
--- a/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py
+++ b/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py
@@ -1,7 +1,7 @@
## @file
# This file is used to check PCD logical expression
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -106,16 +106,21 @@ class _ExprBase:
'>' : '=',
'<' : '='
}
+
for Operator in OpList:
if not self.Token[self.Index:].startswith(Operator):
continue
+
self.Index += len(Operator)
Char = self.Token[self.Index : self.Index + 1]
+
if (Operator in LetterOp and (Char == '_' or Char.isalnum())) \
or (Operator in OpMap and OpMap[Operator] == Char):
self.Index -= len(Operator)
break
+
return True
+
return False
## _LogicalExpressionParser
@@ -166,6 +171,7 @@ class _LogicalExpressionParser(_ExprBase):
return False
return True
+
return False
def IsAtomicNumVal(self):
@@ -216,32 +222,32 @@ class _LogicalExpressionParser(_ExprBase):
#
def LogicalExpression(self):
Ret = self.SpecNot()
- while self.IsCurrentOp(['||', 'OR', 'or', '&&', 'AND', 'and', 'XOR']):
+ while self.IsCurrentOp(['||', 'OR', 'or', '&&', 'AND', 'and', 'XOR', 'xor', '^']):
if self.Token[self.Index-1] == '|' and self.Parens <= 0:
- raise _ExprError(ST.ERR_EXPR_OR)
- if Ret == self.ARITH:
+ raise _ExprError(ST.ERR_EXPR_OR % self.Token)
+ if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
Ret = self.SpecNot()
- if Ret == self.ARITH:
+ if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
Ret = self.REALLOGICAL
return Ret
def SpecNot(self):
- if self.IsCurrentOp(["NOT", "!"]):
+ if self.IsCurrentOp(["NOT", "!", "not"]):
return self.SpecNot()
return self.Rel()
- ## A < B, A > B, A <= B, A >= b
+ ## A < B, A > B, A <= B, A >= B
#
def Rel(self):
Ret = self.Expr()
if self.IsCurrentOp(["<=", ">=", ">", "<", "GT", "LT", "GE", "LE",
"==", "EQ", "!=", "NE"]):
- if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:
+ if Ret == self.STRINGITEM:
raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
Ret = self.Expr()
- if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:
+ if Ret == self.REALLOGICAL:
raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
Ret = self.REALLOGICAL
return Ret
@@ -250,7 +256,7 @@ class _LogicalExpressionParser(_ExprBase):
#
def Expr(self):
Ret = self.Factor()
- while self.IsCurrentOp(["+", "-", "&", "|", "^"]):
+ while self.IsCurrentOp(["+", "-", "&", "|", "^", "XOR", "xor"]):
if self.Token[self.Index-1] == '|' and self.Parens <= 0:
raise _ExprError(ST.ERR_EXPR_OR)
if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:
@@ -281,15 +287,15 @@ class _LogicalExpressionParser(_ExprBase):
return self.ARITH
else:
raise _ExprError(ST.ERR_EXPR_FACTOR % \
- (self.Token, self.Token[self.Index:]))
+ (self.Token[self.Index:], self.Token))
## IsValidLogicalExpression
#
def IsValidLogicalExpression(self):
if self.Len == 0:
- return False, ST.ERR_EXPR_EMPTY
+ return False, ST.ERR_EXPRESS_EMPTY
try:
- if self.LogicalExpression() == self.ARITH:
+ if self.LogicalExpression() not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
return False, ST.ERR_EXPR_LOGICAL % self.Token
except _ExprError, XExcept:
return False, XExcept.Error
@@ -307,55 +313,84 @@ class _ValidRangeExpressionParser(_ExprBase):
'[\t\s]*0[xX][a-fA-F0-9]+[\t\s]*-[\t\s]*0[xX][a-fA-F0-9]+'
def __init__(self, Token):
_ExprBase.__init__(self, Token)
+ self.Parens = 0
+ self.HEX = 1
+ self.INT = 2
+ self.IsParenHappen = False
+ self.IsLogicalOpHappen = False
## IsValidRangeExpression
#
def IsValidRangeExpression(self):
if self.Len == 0:
- return False
+ return False, ST.ERR_EXPR_RANGE_EMPTY
try:
- self.RangeExpression()
- except _ExprError:
- return False
+ if self.RangeExpression() not in [self.HEX, self.INT]:
+ return False, ST.ERR_EXPR_RANGE % self.Token
+ except _ExprError, XExcept:
+ return False, XExcept.Error
+
self.SkipWhitespace()
if self.Index != self.Len:
- return False
- return True
+ return False, (ST.ERR_EXPR_RANGE % self.Token)
+ return True, ''
## RangeExpression
#
def RangeExpression(self):
- self.Unary()
- while self.IsCurrentOp(['OR', 'AND', 'XOR']):
- self.Unary()
+ Ret = self.Unary()
+ while self.IsCurrentOp(['OR', 'AND', 'and', 'or']):
+ self.IsLogicalOpHappen = True
+ if not self.IsParenHappen:
+ raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token)
+ self.IsParenHappen = False
+ Ret = self.Unary()
+
+ if self.IsCurrentOp(['XOR']):
+ Ret = self.Unary()
+
+ return Ret
## Unary
#
def Unary(self):
- if self.IsCurrentOp(["NOT", "-"]):
+ if self.IsCurrentOp(["NOT"]):
return self.Unary()
+
return self.ValidRange()
## ValidRange
#
def ValidRange(self):
+ Ret = -1
if self.IsCurrentOp(["("]):
- self.RangeExpression()
+ self.IsLogicalOpHappen = False
+ self.IsParenHappen = True
+ self.Parens += 1
+ if self.Parens > 1:
+ raise _ExprError(ST.ERR_EXPR_RANGE_DOUBLE_PAREN_NESTED % self.Token)
+ Ret = self.RangeExpression()
if not self.IsCurrentOp([")"]):
- raise _ExprError('')
- return
+ raise _ExprError(ST.ERR_EXPR_RIGHT_PAREN % self.Token)
+ self.Parens -= 1
+ return Ret
+
+ if self.IsLogicalOpHappen:
+ raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token)
- if self.IsCurrentOp(["LT", "GT", "LE", "GE", "EQ"]):
+ if self.IsCurrentOp(["LT", "GT", "LE", "GE", "EQ", "XOR"]):
IntMatch = \
re.compile(self.INT_PATTERN).match(self.Token[self.Index:])
HexMatch = \
re.compile(self.HEX_PATTERN).match(self.Token[self.Index:])
if HexMatch and HexMatch.start() == 0:
self.Index += HexMatch.end()
+ Ret = self.HEX
elif IntMatch and IntMatch.start() == 0:
self.Index += IntMatch.end()
+ Ret = self.INT
else:
- raise _ExprError('')
+ raise _ExprError(ST.ERR_EXPR_RANGE_FACTOR % (self.Token[self.Index:], self.Token))
else:
IntRangeMatch = re.compile(
self.INT_RANGE_PATTERN).match(self.Token[self.Index:]
@@ -365,15 +400,50 @@ class _ValidRangeExpressionParser(_ExprBase):
)
if HexRangeMatch and HexRangeMatch.start() == 0:
self.Index += HexRangeMatch.end()
+ Ret = self.HEX
elif IntRangeMatch and IntRangeMatch.start() == 0:
self.Index += IntRangeMatch.end()
+ Ret = self.INT
else:
- raise _ExprError('')
+ raise _ExprError(ST.ERR_EXPR_RANGE % self.Token)
+
+ return Ret
+
+## _ValidListExpressionParser
+#
+class _ValidListExpressionParser(_ExprBase):
+ VALID_LIST_PATTERN = '(0[xX][0-9a-fA-F]+|[0-9]+)([\t\s]*,[\t\s]*(0[xX][0-9a-fA-F]+|[0-9]+))*'
+ def __init__(self, Token):
+ _ExprBase.__init__(self, Token)
+ self.NUM = 1
- if self.Token[self.Index:self.Index+1] == '_' or \
- self.Token[self.Index:self.Index+1].isalnum():
- raise _ExprError('')
+ def IsValidListExpression(self):
+ if self.Len == 0:
+ return False, ST.ERR_EXPR_LIST_EMPTY
+ try:
+ if self.ListExpression() not in [self.NUM]:
+ return False, ST.ERR_EXPR_LIST % self.Token
+ except _ExprError, XExcept:
+ return False, XExcept.Error
+ self.SkipWhitespace()
+ if self.Index != self.Len:
+ return False, (ST.ERR_EXPR_LIST % self.Token)
+
+ return True, ''
+
+ def ListExpression(self):
+ Ret = -1
+ self.SkipWhitespace()
+ ListMatch = re.compile(self.VALID_LIST_PATTERN).match(self.Token[self.Index:])
+ if ListMatch and ListMatch.start() == 0:
+ self.Index += ListMatch.end()
+ Ret = self.NUM
+ else:
+ raise _ExprError(ST.ERR_EXPR_LIST % self.Token)
+
+ return Ret
+
## _StringTestParser
#
class _StringTestParser(_ExprBase):
@@ -423,37 +493,38 @@ class _StringTestParser(_ExprBase):
self.StringItem()
if not self.IsCurrentOp(["==", "EQ", "!=", "NE"]):
raise _ExprError(ST.ERR_EXPR_EQUALITY % \
- (self.Token, self.Token[self.Index:]))
+ (self.Token[self.Index:], self.Token))
self.StringItem()
if self.Index != self.Len:
raise _ExprError(ST.ERR_EXPR_BOOLEAN % \
(self.Token[self.Index:], self.Token))
##
-# Check syntax of logical expression
+# Check syntax of string test
#
-# @param Token: expression token
+# @param Token: string test token
#
-def IsValidLogicalExpr(Token, Flag=False):
+def IsValidStringTest(Token, Flag=False):
#
# Not do the check right now, keep the implementation for future enhancement.
#
if not Flag:
return True, ""
- return _LogicalExpressionParser(Token).IsValidLogicalExpression()
+ return _StringTestParser(Token).IsValidStringTest()
+
##
-# Check syntax of string test
+# Check syntax of logical expression
#
-# @param Token: string test token
+# @param Token: expression token
#
-def IsValidStringTest(Token, Flag=False):
+def IsValidLogicalExpr(Token, Flag=False):
#
# Not do the check right now, keep the implementation for future enhancement.
#
if not Flag:
return True, ""
- return _StringTestParser(Token).IsValidStringTest()
+ return _LogicalExpressionParser(Token).IsValidLogicalExpression()
##
# Check syntax of range expression
@@ -464,6 +535,14 @@ def IsValidRangeExpr(Token):
return _ValidRangeExpressionParser(Token).IsValidRangeExpression()
##
+# Check syntax of value list expression token
+#
+# @param Token: value list expression token
+#
+def IsValidListExpr(Token):
+ return _ValidListExpressionParser(Token).IsValidListExpression()
+
+##
# Check whether the feature flag expression is valid or not
#
# @param Token: feature flag expression
@@ -486,4 +565,8 @@ def IsValidFeatureFlagExp(Token, Flag=False):
return True, ""
if __name__ == '__main__':
- print _LogicalExpressionParser('a ^ b > a + b').IsValidLogicalExpression()
+# print IsValidRangeExpr('LT 9')
+ print _LogicalExpressionParser('gCrownBayTokenSpaceGuid.PcdPciDevice1BridgeAddressLE0').IsValidLogicalExpression()
+
+
+
diff --git a/BaseTools/Source/Python/UPT/Library/GlobalData.py b/BaseTools/Source/Python/UPT/Library/GlobalData.py
index e47e24a714..d478983c23 100644
--- a/BaseTools/Source/Python/UPT/Library/GlobalData.py
+++ b/BaseTools/Source/Python/UPT/Library/GlobalData.py
@@ -1,7 +1,7 @@
## @file
# This file is used to define common static strings and global data used by UPT
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -92,6 +92,17 @@ gUNPACK_DIR = None
# Flag used to mark whether the INF file is Binary INF or not.
#
gIS_BINARY_INF = False
+
+#
+# Used by FileHook module.
+#
+gRECOVERMGR = None
+
+#
+# Used by PCD parser
+#
+gPackageDict = {}
+
#
# Used by Library instance parser
# {FilePath: FileObj}
diff --git a/BaseTools/Source/Python/UPT/Library/Misc.py b/BaseTools/Source/Python/UPT/Library/Misc.py
index 750805e328..bc9e0e172b 100644
--- a/BaseTools/Source/Python/UPT/Library/Misc.py
+++ b/BaseTools/Source/Python/UPT/Library/Misc.py
@@ -1,7 +1,7 @@
## @file
# Common routines used by all tools
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -41,11 +41,15 @@ from Library import GlobalData
from Library.DataType import SUP_MODULE_LIST
from Library.DataType import END_OF_LINE
from Library.DataType import TAB_SPLIT
-from Library.DataType import LANGUAGE_EN_US
+from Library.DataType import TAB_LANGUAGE_EN_US
+from Library.DataType import TAB_LANGUAGE_EN
+from Library.DataType import TAB_LANGUAGE_EN_X
+from Library.DataType import TAB_UNI_FILE_SUFFIXS
from Library.String import GetSplitValueList
from Library.ParserValidate import IsValidHexVersion
from Library.ParserValidate import IsValidPath
from Object.POM.CommonObject import TextObject
+from Core.FileHook import __FileHookOpen__
## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C
# structure style
@@ -160,14 +164,14 @@ def SaveFileOnChange(File, Content, IsBinaryFile=True):
if os.path.exists(File):
try:
- if Content == open(File, "rb").read():
+ if Content == __FileHookOpen__(File, "rb").read():
return False
except BaseException:
Logger.Error(None, ToolError.FILE_OPEN_FAILURE, ExtraData=File)
CreateDirectory(os.path.dirname(File))
try:
- FileFd = open(File, "wb")
+ FileFd = __FileHookOpen__(File, "wb")
FileFd.write(Content)
FileFd.close()
except BaseException:
@@ -188,6 +192,8 @@ def GetFiles(Root, SkipList=None, FullPath=True):
for Item in SkipList:
if Item in Dirs:
Dirs.remove(Item)
+ if Item in Files:
+ Files.remove(Item)
for Dir in Dirs:
if Dir.startswith('.'):
Dirs.remove(Dir)
@@ -566,39 +572,46 @@ class PathClass(object):
Key = property(_GetFileKey)
-## Check environment variables
+## Get current workspace
#
-# Check environment variables that must be set for build. Currently they are
+# get WORKSPACE from environment variable if present,if not use current working directory as WORKSPACE
#
-# WORKSPACE The directory all packages/platforms start from
-# EDK_TOOLS_PATH The directory contains all tools needed by the build
-# PATH $(EDK_TOOLS_PATH)/Bin/<sys> must be set in PATH
-#
-# If any of above environment variable is not set or has error, the build
-# will be broken.
-#
-def CheckEnvVariable():
+def GetWorkspace():
#
# check WORKSPACE
#
- if "WORKSPACE" not in environ:
- Logger.Error("UPT",
- ToolError.UPT_ENVIRON_MISSING_ERROR,
- ST.ERR_NOT_FOUND_ENVIRONMENT,
- ExtraData="WORKSPACE")
-
- WorkspaceDir = os.path.normpath(environ["WORKSPACE"])
- if not os.path.exists(WorkspaceDir):
- Logger.Error("UPT",
- ToolError.UPT_ENVIRON_MISSING_ERROR,
- ST.ERR_WORKSPACE_NOTEXIST,
- ExtraData="%s" % WorkspaceDir)
- elif ' ' in WorkspaceDir:
- Logger.Error("UPT",
- ToolError.FORMAT_NOT_SUPPORTED,
- ST.ERR_SPACE_NOTALLOWED,
- ExtraData=WorkspaceDir)
+ if "WORKSPACE" in environ:
+ WorkspaceDir = os.path.normpath(environ["WORKSPACE"])
+ if not os.path.exists(WorkspaceDir):
+ Logger.Error("UPT",
+ ToolError.UPT_ENVIRON_MISSING_ERROR,
+ ST.ERR_WORKSPACE_NOTEXIST,
+ ExtraData="%s" % WorkspaceDir)
+ else:
+ WorkspaceDir = os.getcwd()
+ if WorkspaceDir[-1] == ':':
+ WorkspaceDir += os.sep
+ return WorkspaceDir
+
+## Get relative path
+#
+# use full path and workspace to get relative path
+# the destination of this function is mainly to resolve the root path issue(like c: or c:\)
+#
+# @param Fullpath: a string of fullpath
+# @param Workspace: a string of workspace
+#
+def GetRelativePath(Fullpath, Workspace):
+
+ RelativePath = ''
+ if Workspace.endswith(os.sep):
+ RelativePath = Fullpath[Fullpath.upper().find(Workspace.upper())+len(Workspace):]
+ else:
+ RelativePath = Fullpath[Fullpath.upper().find(Workspace.upper())+len(Workspace)+1:]
+
+ return RelativePath
+
## Check whether all module types are in list
#
# check whether all module types (SUP_MODULE_LIST) are in list
@@ -644,7 +657,7 @@ class MergeCommentDict(dict):
#
def GenDummyHelpTextObj():
HelpTxt = TextObject()
- HelpTxt.SetLang(LANGUAGE_EN_US)
+ HelpTxt.SetLang(TAB_LANGUAGE_EN_US)
HelpTxt.SetString(' ')
return HelpTxt
@@ -972,3 +985,136 @@ def GetLibInstanceInfo(String, WorkSpace, LineNo):
VerString = GetSplitValueList(VerString, '=', 1)[1]
return FileGuidString, VerString
+
+## GetLocalValue
+#
+# Generate the local value for INF and DEC file. If Lang attribute not present, then use this value.
+# If present, and there is no element without the Lang attribute, and one of the elements has the rfc1766 code is
+# "en-x-tianocore", or "en-US" if "en-x-tianocore" was not found, or "en" if "en-US" was not found, or startswith 'en'
+# if 'en' was not found, then use this value.
+# If multiple entries of a tag exist which have the same language code, use the last entry.
+#
+# @param ValueList A list need to be processed.
+# @param UseFirstValue: True to use the first value, False to use the last value
+#
+# @return LocalValue
+def GetLocalValue(ValueList, UseFirstValue=False):
+ Value1 = ''
+ Value2 = ''
+ Value3 = ''
+ Value4 = ''
+ Value5 = ''
+ for (Key, Value) in ValueList:
+ if Key == TAB_LANGUAGE_EN_X:
+ if UseFirstValue:
+ if not Value1:
+ Value1 = Value
+ else:
+ Value1 = Value
+ if Key == TAB_LANGUAGE_EN_US:
+ if UseFirstValue:
+ if not Value2:
+ Value2 = Value
+ else:
+ Value2 = Value
+ if Key == TAB_LANGUAGE_EN:
+ if UseFirstValue:
+ if not Value3:
+ Value3 = Value
+ else:
+ Value3 = Value
+ if Key.startswith(TAB_LANGUAGE_EN):
+ if UseFirstValue:
+ if not Value4:
+ Value4 = Value
+ else:
+ Value4 = Value
+ if Key == '':
+ if UseFirstValue:
+ if not Value5:
+ Value5 = Value
+ else:
+ Value5 = Value
+
+ if Value1:
+ return Value1
+ if Value2:
+ return Value2
+ if Value3:
+ return Value3
+ if Value4:
+ return Value4
+ if Value5:
+ return Value5
+
+ return ''
+
+
+## GetCharIndexOutStr
+#
+# Get comment character index outside a string
+#
+# @param Line: The string to be checked
+# @param CommentCharacter: Comment char, used to ignore comment content
+#
+# @retval Index
+#
+def GetCharIndexOutStr(CommentCharacter, Line):
+ #
+ # remove whitespace
+ #
+ Line = Line.strip()
+
+ #
+ # Check whether comment character is in a string
+ #
+ InString = False
+ for Index in range(0, len(Line)):
+ if Line[Index] == '"':
+ InString = not InString
+ elif Line[Index] == CommentCharacter and InString :
+ pass
+ elif Line[Index] == CommentCharacter and (Index +1) < len(Line) and Line[Index+1] == CommentCharacter \
+ and not InString :
+ return Index
+ return -1
+
+## ValidateUNIFilePath
+#
+# Check the UNI file path
+#
+# @param FilePath: The UNI file path
+#
+def ValidateUNIFilePath(Path):
+ Suffix = Path[Path.rfind(TAB_SPLIT):]
+
+ #
+ # Check if the suffix is one of the '.uni', '.UNI', '.Uni'
+ #
+ if Suffix not in TAB_UNI_FILE_SUFFIXS:
+ Logger.Error("Unicode File Parser",
+ ToolError.FORMAT_INVALID,
+ Message=ST.ERR_UNI_FILE_SUFFIX_WRONG,
+ ExtraData=Path)
+
+ #
+ # Check if '..' in the file name(without suffixe)
+ #
+ if (TAB_SPLIT + TAB_SPLIT) in Path:
+ Logger.Error("Unicode File Parser",
+ ToolError.FORMAT_INVALID,
+ Message=ST.ERR_UNI_FILE_NAME_INVALID,
+ ExtraData=Path)
+
+ #
+ # Check if the file name is valid according to the DEC and INF specification
+ #
+ Pattern = '[a-zA-Z0-9_][a-zA-Z0-9_\-\.]*'
+ FileName = Path.replace(Suffix, '')
+ InvalidCh = re.sub(Pattern, '', FileName)
+ if InvalidCh:
+ Logger.Error("Unicode File Parser",
+ ToolError.FORMAT_INVALID,
+ Message=ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID,
+ ExtraData=Path)
+
diff --git a/BaseTools/Source/Python/UPT/Library/ParserValidate.py b/BaseTools/Source/Python/UPT/Library/ParserValidate.py
index 860fb4f1dc..bfb4bc749f 100644
--- a/BaseTools/Source/Python/UPT/Library/ParserValidate.py
+++ b/BaseTools/Source/Python/UPT/Library/ParserValidate.py
@@ -1,6 +1,7 @@
## @file ParserValidate.py
+# Functions for parser validation
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -566,7 +567,7 @@ def IsValidPcdValue(PcdValue):
for Char in PcdValue:
if Char == '\n' or Char == '\t' or Char == '\f':
return False
-
+
#
# <Boolean>
#
@@ -582,7 +583,7 @@ def IsValidPcdValue(PcdValue):
if IsValidHex(PcdValue):
return True
- ReIsValidIntegerSingle = re.compile(r"^\s*[0-9]\s*$", re.DOTALL)
+ ReIsValidIntegerSingle = re.compile(r"^\s*[0-9]\s*$", re.DOTALL)
if ReIsValidIntegerSingle.match(PcdValue) != None:
return True
@@ -590,7 +591,6 @@ def IsValidPcdValue(PcdValue):
if ReIsValidIntegerMulti.match(PcdValue) != None:
return True
-
#
# <StringVal> ::= {<StringType>} {<Array>} {"$(" <MACRO> ")"}
# <StringType> ::= {<UnicodeString>} {<CString>}
diff --git a/BaseTools/Source/Python/UPT/Library/Parsing.py b/BaseTools/Source/Python/UPT/Library/Parsing.py
index 95c51406b2..db0fec3a73 100644
--- a/BaseTools/Source/Python/UPT/Library/Parsing.py
+++ b/BaseTools/Source/Python/UPT/Library/Parsing.py
@@ -2,7 +2,7 @@
# This file is used to define common parsing related functions used in parsing
# INF/DEC/DSC process
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -42,6 +42,7 @@ from Logger import StringTable as ST
import Logger.Log as Logger
from Parser.DecParser import Dec
+import GlobalData
gPKG_INFO_DICT = {}
@@ -53,7 +54,7 @@ gPKG_INFO_DICT = {}
# @param String: String with BuildOption statement
# @param File: The file which defines build option, used in error report
#
-def GetBuildOption(String, File, LineNo=-1):
+def GetBuildOption(String, File, LineNo= -1):
(Family, ToolChain, Flag) = ('', '', '')
if String.find(DataType.TAB_EQUAL_SPLIT) < 0:
RaiseParserError(String, 'BuildOptions', File, \
@@ -76,7 +77,7 @@ def GetBuildOption(String, File, LineNo=-1):
# @param ContainerFile: The file which describes the library class, used for
# error report
#
-def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo=-1):
+def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1):
List = GetSplitValueList(Item[0])
SupMod = DataType.SUP_MODULE_LIST_STRING
if len(List) != 2:
@@ -101,7 +102,7 @@ def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo=-1):
# @param ContainerFile: The file which describes the library class, used for
# error report
#
-def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo = -1):
+def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo= -1):
ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2))
SupMod = DataType.SUP_MODULE_LIST_STRING
@@ -131,7 +132,7 @@ def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo = -1):
# @param Section: Used for error report
# @param File: Used for error report
#
-def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo=-1):
+def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo= -1):
Format = '<TokenSpaceGuidCName>.<PcdCName>'
if TokenInfoString != '' and TokenInfoString != None:
TokenInfoList = GetSplitValueList(TokenInfoString, DataType.TAB_SPLIT)
@@ -151,7 +152,7 @@ def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo=-1):
# report
#
-def GetPcd(Item, Type, ContainerFile, LineNo=-1):
+def GetPcd(Item, Type, ContainerFile, LineNo= -1):
TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', ''
List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
@@ -178,7 +179,7 @@ def GetPcd(Item, Type, ContainerFile, LineNo=-1):
# @param ContainerFile: The file which describes the pcd, used for error
# report
#
-def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo=-1):
+def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo= -1):
TokenGuid, TokenName, Value = '', '', ''
List = GetSplitValueList(Item)
if len(List) != 2:
@@ -202,7 +203,7 @@ def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo=-1):
# @param ContainerFile: The file which describes the pcd, used for error
# report
#
-def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo=-1):
+def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo= -1):
TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', ''
List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
if len(List) < 4 or len(List) > 8:
@@ -228,7 +229,7 @@ def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo=-1):
# @param ContainerFile: The file which describes the pcd, used for error
# report
#
-def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo = -1):
+def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo= -1):
TokenGuid, TokenName, List1, List2, List3, List4, List5 = \
'', '', '', '', '', '', ''
List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
@@ -255,7 +256,7 @@ def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo = -1):
# @param ContainerFile: The file which describes the pcd, used for error
# report
#
-def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo=-1):
+def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo= -1):
TokenGuid, TokenName, List1, List2 = '', '', '', ''
List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT)
if len(List) < 3 or len(List) > 4:
@@ -533,7 +534,7 @@ def GetComponents(Lines, KeyValues, CommentCharacter):
# @param ContainerFile: The file which describes the library class, used
# for error report
#
-def GetSource(Item, ContainerFile, FileRelativePath, LineNo=-1):
+def GetSource(Item, ContainerFile, FileRelativePath, LineNo= -1):
ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4
List = GetSplitValueList(ItemNew)
if len(List) < 5 or len(List) > 9:
@@ -558,7 +559,7 @@ def GetSource(Item, ContainerFile, FileRelativePath, LineNo=-1):
# @param ContainerFile: The file which describes the library class,
# used for error report
#
-def GetBinary(Item, ContainerFile, LineNo=-1):
+def GetBinary(Item, ContainerFile, LineNo= -1):
ItemNew = Item + DataType.TAB_VALUE_SPLIT
List = GetSplitValueList(ItemNew)
if len(List) < 3 or len(List) > 5:
@@ -596,7 +597,7 @@ def GetGuidsProtocolsPpisOfInf(Item):
# @param ContainerFile: The file which describes the library class,
# used for error report
#
-def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo=-1):
+def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo= -1):
List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)
if len(List) != 2:
RaiseParserError(Item, Type, ContainerFile, '<CName>=<GuidValue>', \
@@ -614,7 +615,7 @@ def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo=-1):
RegisterFormatGuid = List[1]
else:
RaiseParserError(Item, Type, ContainerFile, \
- 'CFormat or RegisterFormat', LineNo)
+ 'CFormat or RegisterFormat', LineNo)
return (List[0], RegisterFormatGuid)
@@ -627,7 +628,7 @@ def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo=-1):
# @param ContainerFile: The file which describes the library class,
# used for error report
#
-def GetPackage(Item, ContainerFile, FileRelativePath, LineNo=-1):
+def GetPackage(Item, ContainerFile, FileRelativePath, LineNo= -1):
ItemNew = Item + DataType.TAB_VALUE_SPLIT
List = GetSplitValueList(ItemNew)
CheckFileType(List[0], '.Dec', ContainerFile, 'package', List[0], LineNo)
@@ -683,7 +684,7 @@ def GetPcdOfInf(Item, Type, File, LineNo):
# @param File: Dec file
# @param LineNo: Line number
#
-def GetPcdOfDec(Item, Type, File, LineNo=-1):
+def GetPcdOfDec(Item, Type, File, LineNo= -1):
Format = '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'
TokenGuid, TokenName, Value, DatumType, Token = '', '', '', '', ''
List = GetSplitValueList(Item)
@@ -756,7 +757,7 @@ def InsertSectionItems(Model, SectionItemList, ArchList, \
LineValue, StartLine, Comment = SectionItem[0], \
SectionItem[1], SectionItem[2]
- Logger.Debug(4, ST.MSG_PARSING %LineValue)
+ Logger.Debug(4, ST.MSG_PARSING % LineValue)
#
# And then parse DEFINE statement
#
@@ -782,7 +783,7 @@ def GenMetaDatSectionItem(Key, Value, List):
List[Key] = [Value]
else:
List[Key].append(Value)
-
+
## GetPkgInfoFromDec
#
# get package name, guid, version info from dec files
@@ -793,17 +794,23 @@ def GetPkgInfoFromDec(Path):
PkgName = None
PkgGuid = None
PkgVersion = None
-
+
Path = Path.replace('\\', '/')
-
+
if not os.path.exists(Path):
- Logger.Error("\nUPT", FILE_NOT_FOUND, File = Path)
+ Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path)
if Path in gPKG_INFO_DICT:
return gPKG_INFO_DICT[Path]
try:
- DecParser = Dec(Path)
+ DecParser = None
+ if Path not in GlobalData.gPackageDict:
+ DecParser = Dec(Path)
+ GlobalData.gPackageDict[Path] = DecParser
+ else:
+ DecParser = GlobalData.gPackageDict[Path]
+
PkgName = DecParser.GetPackageName()
PkgGuid = DecParser.GetPackageGuid()
PkgVersion = DecParser.GetPackageVersion()
@@ -819,7 +826,7 @@ def GetPkgInfoFromDec(Path):
#
def GetWorkspacePackage():
DecFileList = []
- WorkspaceDir = os.environ["WORKSPACE"]
+ WorkspaceDir = GlobalData.gWORKSPACE
for Root, Dirs, Files in os.walk(WorkspaceDir):
if 'CVS' in Dirs:
Dirs.remove('CVS')
@@ -843,7 +850,7 @@ def GetWorkspacePackage():
(PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile)
if PkgName and PkgGuid and PkgVersion:
PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile))
-
+
return PkgList
## GetWorkspaceModule
@@ -852,7 +859,7 @@ def GetWorkspacePackage():
#
def GetWorkspaceModule():
InfFileList = []
- WorkspaceDir = os.environ["WORKSPACE"]
+ WorkspaceDir = GlobalData.gWORKSPACE
for Root, Dirs, Files in os.walk(WorkspaceDir):
if 'CVS' in Dirs:
Dirs.remove('CVS')
@@ -870,7 +877,7 @@ def GetWorkspaceModule():
if Ext.lower() in ['.inf']:
InfFileList.append\
(os.path.normpath(os.path.join(Root, FileSp)))
-
+
return InfFileList
## MacroParser used to parse macro definition
@@ -890,7 +897,7 @@ def MacroParser(Line, FileName, SectionType, FileLocalMacros):
# Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
#
return None, None
-
+
TokenList = GetSplitValueList(LineContent[Match.end(1):], \
DataType.TAB_EQUAL_SPLIT, 1)
#
@@ -910,16 +917,16 @@ def MacroParser(Line, FileName, SectionType, FileLocalMacros):
#
if SectionType == DataType.MODEL_META_DATA_HEADER:
FileLocalMacros[Name] = Value
-
+
ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL)
if ReIsValidMacroName.match(Name) == None:
- Logger.Error('Parser',
- FORMAT_INVALID,
- ST.ERR_MACRONAME_INVALID%(Name),
- ExtraData=LineContent,
- File=FileName,
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_MACRONAME_INVALID % (Name),
+ ExtraData=LineContent,
+ File=FileName,
Line=LineNo)
-
+
# Validate MACRO Value
#
# <MacroDefinition> ::= [<Comments>]{0,}
@@ -932,13 +939,13 @@ def MacroParser(Line, FileName, SectionType, FileLocalMacros):
#
ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL)
if ReIsValidMacroValue.match(Value) == None:
- Logger.Error('Parser',
- FORMAT_INVALID,
- ST.ERR_MACROVALUE_INVALID%(Value),
- ExtraData=LineContent,
- File=FileName,
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_MACROVALUE_INVALID % (Value),
+ ExtraData=LineContent,
+ File=FileName,
Line=LineNo)
-
+
return Name, Value
## GenSection
@@ -952,7 +959,7 @@ def MacroParser(Line, FileName, SectionType, FileLocalMacros):
# seperated by space,
# value is statement
#
-def GenSection(SectionName, SectionDict, SplitArch=True):
+def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False):
Content = ''
for SectionAttrs in SectionDict:
StatementList = SectionDict[SectionAttrs]
@@ -969,11 +976,29 @@ def GenSection(SectionName, SectionDict, SplitArch=True):
Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']'
else:
Section = '[' + SectionName + ']'
- Content += '\n\n' + Section + '\n'
+ Content += '\n' + Section + '\n'
if StatementList != None:
for Statement in StatementList:
- Content += Statement + '\n'
+ LineList = Statement.split('\n')
+ NewStatement = ""
+ for Line in LineList:
+ # ignore blank comment
+ if not Line.replace("#", '').strip() and SectionName != 'Defines':
+ continue
+ # add two space before non-comments line except the comments in Defines section
+ if Line.strip().startswith('#') and SectionName == 'Defines':
+ NewStatement += "%s\n" % Line
+ continue
+ NewStatement += " %s\n" % Line
+ if NeedBlankLine:
+ Content += NewStatement + '\n'
+ else:
+ Content += NewStatement
+ if NeedBlankLine:
+ Content = Content[:-1]
+ if not Content.replace('\\n', '').strip():
+ return ''
return Content
## ConvertArchForInstall
@@ -984,10 +1009,10 @@ def GenSection(SectionName, SectionDict, SplitArch=True):
# @return: the arch string that get converted
#
def ConvertArchForInstall(Arch):
- if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64,
+ if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64,
DataType.TAB_ARCH_IPF, DataType.TAB_ARCH_EBC]:
Arch = Arch.upper()
elif Arch.upper() == DataType.TAB_ARCH_COMMON:
Arch = Arch.lower()
-
+
return Arch
diff --git a/BaseTools/Source/Python/UPT/Library/String.py b/BaseTools/Source/Python/UPT/Library/String.py
index f709ff1bce..37ce1418ae 100644
--- a/BaseTools/Source/Python/UPT/Library/String.py
+++ b/BaseTools/Source/Python/UPT/Library/String.py
@@ -1,12 +1,12 @@
## @file
-# This file is used to define common string related functions used in parsing
+# This file is used to define common string related functions used in parsing
# process
#
# Copyright (c) 2011 - 2014, 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
+# 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,
@@ -43,7 +43,7 @@ gMACRO_PATTERN = re.compile("\$\(([_A-Z][_A-Z0-9]*)\)", re.UNICODE)
# @param MaxSplit: The max number of split values, default is -1
#
#
-def GetSplitValueList(String, SplitTag=DataType.TAB_VALUE_SPLIT, MaxSplit=-1):
+def GetSplitValueList(String, SplitTag=DataType.TAB_VALUE_SPLIT, MaxSplit= -1):
return map(lambda l: l.strip(), String.split(SplitTag, MaxSplit))
## MergeArches
@@ -129,7 +129,7 @@ def GetDynamics(Lines, Key, KeyValues, CommentCharacter):
## SplitModuleType
#
# Split ModuleType out of section defien to get key
-# [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [
+# [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [
# 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]
#
# @param Key: String to be parsed
@@ -164,7 +164,7 @@ def SplitModuleType(Key):
# @param Line: The content contain line string and line number
# @param FileName: The meta-file file name
#
-def ReplaceMacro(String, MacroDefinitions = None, SelfReplacement = False, Line = None, FileName = None, Flag = False):
+def ReplaceMacro(String, MacroDefinitions=None, SelfReplacement=False, Line=None, FileName=None, Flag=False):
LastString = String
if MacroDefinitions == None:
MacroDefinitions = {}
@@ -184,10 +184,10 @@ def ReplaceMacro(String, MacroDefinitions = None, SelfReplacement = False, Line
Count += 1
if Count % 2 != 0:
MacroString += QuotedStringItem
-
- if Count == len(QuotedStringList) and Count%2 == 0:
+
+ if Count == len(QuotedStringList) and Count % 2 == 0:
MacroString += QuotedStringItem
-
+
MacroUsed = gMACRO_PATTERN.findall(MacroString)
#
# no macro found in String, stop replacing
@@ -198,7 +198,7 @@ def ReplaceMacro(String, MacroDefinitions = None, SelfReplacement = False, Line
if Macro not in MacroDefinitions:
if SelfReplacement:
String = String.replace("$(%s)" % Macro, '')
- Logger.Debug(5, "Delete undefined MACROs in file %s line %d: %s!" %(FileName, Line[1], Line[0]))
+ Logger.Debug(5, "Delete undefined MACROs in file %s line %d: %s!" % (FileName, Line[1], Line[0]))
continue
if not HaveQuotedMacroFlag:
String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro])
@@ -207,25 +207,25 @@ def ReplaceMacro(String, MacroDefinitions = None, SelfReplacement = False, Line
for QuotedStringItem in QuotedStringList:
Count += 1
if Count % 2 != 0:
- QuotedStringList[Count-1] = QuotedStringList[Count-1].replace("$(%s)" % Macro,
+ QuotedStringList[Count - 1] = QuotedStringList[Count - 1].replace("$(%s)" % Macro,
MacroDefinitions[Macro])
- elif Count == len(QuotedStringList) and Count%2 == 0:
- QuotedStringList[Count-1] = QuotedStringList[Count-1].replace("$(%s)" % Macro,
+ elif Count == len(QuotedStringList) and Count % 2 == 0:
+ QuotedStringList[Count - 1] = QuotedStringList[Count - 1].replace("$(%s)" % Macro,
MacroDefinitions[Macro])
-
+
RetString = ''
if HaveQuotedMacroFlag:
Count = 0
for QuotedStringItem in QuotedStringList:
- Count += 1
+ Count += 1
if Count != len(QuotedStringList):
- RetString += QuotedStringList[Count-1] + "\""
+ RetString += QuotedStringList[Count - 1] + "\""
else:
- RetString += QuotedStringList[Count-1]
-
+ RetString += QuotedStringList[Count - 1]
+
String = RetString
-
- #
+
+ #
# in case there's macro not defined
#
if String == LastString:
@@ -242,7 +242,7 @@ def ReplaceMacro(String, MacroDefinitions = None, SelfReplacement = False, Line
# @param Path: The input value for Path to be converted
# @param Defines: A set for DEFINE statement
#
-def NormPath(Path, Defines = None):
+def NormPath(Path, Defines=None):
IsRelativePath = False
if Defines == None:
Defines = {}
@@ -269,7 +269,7 @@ def NormPath(Path, Defines = None):
# Remove spaces
#
# @param Line: The string to be cleaned
-# @param CommentCharacter: Comment char, used to ignore comment content,
+# @param CommentCharacter: Comment char, used to ignore comment content,
# default is DataType.TAB_COMMENT_SPLIT
#
def CleanString(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):
@@ -305,7 +305,7 @@ def CleanString(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyle
# Remove spaces
#
# @param Line: The string to be cleaned
-# @param CommentCharacter: Comment char, used to ignore comment content,
+# @param CommentCharacter: Comment char, used to ignore comment content,
# default is DataType.TAB_COMMENT_SPLIT
#
def CleanString2(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False):
@@ -394,10 +394,10 @@ def GetDefineValue(String, Key, CommentCharacter):
# @param CommentCharacter: Comment char, be used to ignore comment content
# @param KeySplitCharacter: Key split char, between key name and key value.
# Key1 = Value1, '=' is the key split char
-# @param ValueSplitFlag: Value split flag, be used to decide if has
+# @param ValueSplitFlag: Value split flag, be used to decide if has
# multiple values
-# @param ValueSplitCharacter: Value split char, be used to split multiple
-# values. Key1 = Value1|Value2, '|' is the value
+# @param ValueSplitCharacter: Value split char, be used to split multiple
+# values. Key1 = Value1|Value2, '|' is the value
# split char
#
def GetSingleValueOfKeyFromLines(Lines, Dictionary, CommentCharacter, KeySplitCharacter, \
@@ -489,7 +489,7 @@ def PreCheck(FileName, FileContent, SupSectionTag):
#
if Line.find('$') > -1:
if Line.find('$(') < 0 or Line.find(')') < 0:
- Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = Logger.IS_RAISE_ERROR)
+ Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)
#
# Check []
#
@@ -498,14 +498,14 @@ def PreCheck(FileName, FileContent, SupSectionTag):
# Only get one '[' or one ']'
#
if not (Line.find('[') > -1 and Line.find(']') > -1):
- Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = Logger.IS_RAISE_ERROR)
+ Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)
#
# Regenerate FileContent
#
NewFileContent = NewFileContent + Line + '\r\n'
if IsFailed:
- Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = Logger.IS_RAISE_ERROR)
+ Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR)
return NewFileContent
@@ -523,7 +523,7 @@ def PreCheck(FileName, FileContent, SupSectionTag):
# @param Line: The line in container file which defines the file
# to be checked
#
-def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo=-1):
+def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo= -1):
if CheckFilename != '' and CheckFilename != None:
(Root, Ext) = os.path.splitext(CheckFilename)
if Ext.upper() != ExtName.upper() and Root:
@@ -544,13 +544,13 @@ def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line,
#
# @param CheckFilename: Name of the file to be checked
# @param WorkspaceDir: Current workspace dir
-# @param ContainerFilename: The container file which describes the file to
+# @param ContainerFilename: The container file which describes the file to
# be checked, used for error report
# @param SectionName: Used for error report
-# @param Line: The line in container file which defines the
+# @param Line: The line in container file which defines the
# file to be checked
#
-def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo=-1):
+def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo= -1):
CheckFile = ''
if CheckFilename != '' and CheckFilename != None:
CheckFile = WorkspaceFile(WorkspaceDir, CheckFilename)
@@ -560,7 +560,7 @@ def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName,
LineNo = GetLineNo(ContainerFile, Line)
ErrorMsg = ST.ERR_CHECKFILE_NOTFOUND % (CheckFile, SectionName)
Logger.Error("Parser", PARSER_ERROR, ErrorMsg,
- File=ContainerFilename, Line = LineNo, RaiseError=Logger.IS_RAISE_ERROR)
+ File=ContainerFilename, Line=LineNo, RaiseError=Logger.IS_RAISE_ERROR)
return CheckFile
## GetLineNo
@@ -593,7 +593,7 @@ def GetLineNo(FileContent, Line, IsIgnoreComment=True):
# @param File: File which has the string
# @param Format: Correct format
#
-def RaiseParserError(Line, Section, File, Format='', LineNo=-1):
+def RaiseParserError(Line, Section, File, Format='', LineNo= -1):
if LineNo == -1:
LineNo = GetLineNo(open(os.path.normpath(File), 'r').read(), Line)
ErrorMsg = ST.ERR_INVALID_NOTFOUND % (Line, Section)
@@ -650,7 +650,7 @@ def ConvertToSqlString2(String):
# @param Lines: string list
# @param Split: split character
#
-def GetStringOfList(List, Split = ' '):
+def GetStringOfList(List, Split=' '):
if type(List) != type([]):
return List
Str = ''
@@ -696,7 +696,7 @@ def StringArrayLength(String):
# @param OptionString: the option string
# @param Which: Which flag
# @param Against: Against flag
-#
+#
def RemoveDupOption(OptionString, Which="/I", Against=None):
OptionList = OptionString.split()
ValueList = []
@@ -718,14 +718,14 @@ def RemoveDupOption(OptionString, Which="/I", Against=None):
## Check if the string is HexDgit
#
-# Return true if all characters in the string are digits and there is at
-# least one character
+# Return true if all characters in the string are digits and there is at
+# least one character
# or valid Hexs (started with 0x, following by hexdigit letters)
-# , false otherwise.
+# , false otherwise.
# @param string: input string
#
def IsHexDigit(Str):
- try:
+ try:
int(Str, 10)
return True
except ValueError:
@@ -737,16 +737,16 @@ def IsHexDigit(Str):
return False
return False
-## Check if the string is HexDgit and its integer value within limit of UINT32
+## Check if the string is HexDgit and its interger value within limit of UINT32
#
-# Return true if all characters in the string are digits and there is at
-# least one character
+# Return true if all characters in the string are digits and there is at
+# least one character
# or valid Hexs (started with 0x, following by hexdigit letters)
-# , false otherwise.
+# , false otherwise.
# @param string: input string
#
def IsHexDigitUINT32(Str):
- try:
+ try:
Value = int(Str, 10)
if (Value <= 0xFFFFFFFF) and (Value >= 0):
return True
@@ -761,11 +761,11 @@ def IsHexDigitUINT32(Str):
return False
## CleanSpecialChar
-#
-# The ASCII text files of type INF, DEC, INI are edited by developers,
+#
+# The ASCII text files of type INF, DEC, INI are edited by developers,
# and may contain characters that cannot be directly translated to strings that
-# are conformant with the UDP XML Schema. Any characters in this category
-# (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF)
+# are conformant with the UDP XML Schema. Any characters in this category
+# (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF)
# must be converted to a space character[0x20] as part of the parsing process.
#
def ConvertSpecialChar(Lines):
@@ -773,7 +773,7 @@ def ConvertSpecialChar(Lines):
for line in Lines:
ReMatchSpecialChar = re.compile(r"[\x00-\x08]|\x09|\x0b|\x0c|[\x0e-\x1f]|[\x7f-\xff]")
RetLines.append(ReMatchSpecialChar.sub(' ', line))
-
+
return RetLines
## __GetTokenList
@@ -817,7 +817,7 @@ def __GetTokenList(Str):
if TokenOP:
List.append(TokenOP)
TokenOP = ''
-
+
if PreChar == '\\' and Char == '\\':
PreChar = ''
else:
@@ -870,61 +870,55 @@ def ConvertNOTEQToNE(Expr):
return ''.join(RetList)
## SplitPcdEntry
-#
+#
# Split an PCD entry string to Token.CName and PCD value and FFE.
# NOTE: PCD Value and FFE can contain "|" in it's expression. And in INF specification, have below rule.
-# When using the characters "|" or "||" in an expression, the expression must be encapsulated in
+# When using the characters "|" or "||" in an expression, the expression must be encapsulated in
# open "(" and close ")" parenthesis.
-#
+#
# @param String An PCD entry string need to be split.
-#
-# @return List [PcdTokenCName, Value, FFE]
+#
+# @return List [PcdTokenCName, Value, FFE]
#
def SplitPcdEntry(String):
if not String:
- return ['', '',''], False
-
+ return ['', '', ''], False
+
PcdTokenCName = ''
PcdValue = ''
PcdFeatureFlagExp = ''
-
+
ValueList = GetSplitValueList(String, "|", 1)
-
+
#
# Only contain TokenCName
#
if len(ValueList) == 1:
return [ValueList[0]], True
-
+
NewValueList = []
-
+
if len(ValueList) == 2:
PcdTokenCName = ValueList[0]
- ValueList = GetSplitValueList(ValueList[1], "|")
-
- RemainCount = 0
- for Item in ValueList:
- ParenthesisCount = 0
- for Char in Item:
- if Char == "(":
- ParenthesisCount += 1
- if Char == ")":
- ParenthesisCount -= 1
-
- #
- # An individual item
- #
- if RemainCount == 0 and ParenthesisCount >= 0:
- NewValueList.append(Item)
- RemainCount = ParenthesisCount
- elif RemainCount > 0 and RemainCount + ParenthesisCount >= 0:
- NewValueList[-1] = NewValueList[-1] + '|' + Item
- RemainCount = RemainCount + ParenthesisCount
- elif RemainCount > 0 and RemainCount + ParenthesisCount < 0:
- #
- # ERROR, return
- #
- return ['', '', ''], False
+
+ InQuote = False
+ InParenthesis = False
+ StrItem = ''
+ for StrCh in ValueList[1]:
+ if StrCh == '"':
+ InQuote = not InQuote
+ elif StrCh == '(' or StrCh == ')':
+ InParenthesis = not InParenthesis
+
+ if StrCh == '|':
+ if not InQuote or not InParenthesis:
+ NewValueList.append(StrItem.strip())
+ StrItem = ' '
+ continue
+
+ StrItem += StrCh
+
+ NewValueList.append(StrItem.strip())
if len(NewValueList) == 1:
PcdValue = NewValueList[0]
@@ -935,7 +929,7 @@ def SplitPcdEntry(String):
return [PcdTokenCName, PcdValue, PcdFeatureFlagExp], True
else:
return ['', '', ''], False
-
+
return ['', '', ''], False
## Check if two arches matched?
diff --git a/BaseTools/Source/Python/UPT/Library/UniClassObject.py b/BaseTools/Source/Python/UPT/Library/UniClassObject.py
new file mode 100644
index 0000000000..d542dc5dc8
--- /dev/null
+++ b/BaseTools/Source/Python/UPT/Library/UniClassObject.py
@@ -0,0 +1,1042 @@
+## @file
+# Collect all defined strings in multiple uni files.
+#
+# Copyright (c) 2014, 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.
+#
+"""
+Collect all defined strings in multiple uni files
+"""
+
+##
+# Import Modules
+#
+import os, codecs, re
+import distutils.util
+from Logger import ToolError
+from Logger import Log as EdkLogger
+from Logger import StringTable as ST
+from Library.String import GetLineNo
+from Library.Misc import PathClass
+from Library.Misc import GetCharIndexOutStr
+from Library import DataType as DT
+
+##
+# Static definitions
+#
+UNICODE_WIDE_CHAR = u'\\wide'
+UNICODE_NARROW_CHAR = u'\\narrow'
+UNICODE_NON_BREAKING_CHAR = u'\\nbr'
+UNICODE_UNICODE_CR = '\r'
+UNICODE_UNICODE_LF = '\n'
+
+NARROW_CHAR = u'\uFFF0'
+WIDE_CHAR = u'\uFFF1'
+NON_BREAKING_CHAR = u'\uFFF2'
+CR = u'\u000D'
+LF = u'\u000A'
+NULL = u'\u0000'
+TAB = u'\t'
+BACK_SPLASH = u'\\'
+
+gINCLUDE_PATTERN = re.compile("^!include[\s]+([\S]+)[\s]*$", re.MULTILINE | re.UNICODE)
+
+gLANG_CONV_TABLE = {'eng':'en', 'fra':'fr', \
+ 'aar':'aa', 'abk':'ab', 'ave':'ae', 'afr':'af', 'aka':'ak', 'amh':'am', \
+ 'arg':'an', 'ara':'ar', 'asm':'as', 'ava':'av', 'aym':'ay', 'aze':'az', \
+ 'bak':'ba', 'bel':'be', 'bul':'bg', 'bih':'bh', 'bis':'bi', 'bam':'bm', \
+ 'ben':'bn', 'bod':'bo', 'bre':'br', 'bos':'bs', 'cat':'ca', 'che':'ce', \
+ 'cha':'ch', 'cos':'co', 'cre':'cr', 'ces':'cs', 'chu':'cu', 'chv':'cv', \
+ 'cym':'cy', 'dan':'da', 'deu':'de', 'div':'dv', 'dzo':'dz', 'ewe':'ee', \
+ 'ell':'el', 'epo':'eo', 'spa':'es', 'est':'et', 'eus':'eu', 'fas':'fa', \
+ 'ful':'ff', 'fin':'fi', 'fij':'fj', 'fao':'fo', 'fry':'fy', 'gle':'ga', \
+ 'gla':'gd', 'glg':'gl', 'grn':'gn', 'guj':'gu', 'glv':'gv', 'hau':'ha', \
+ 'heb':'he', 'hin':'hi', 'hmo':'ho', 'hrv':'hr', 'hat':'ht', 'hun':'hu', \
+ 'hye':'hy', 'her':'hz', 'ina':'ia', 'ind':'id', 'ile':'ie', 'ibo':'ig', \
+ 'iii':'ii', 'ipk':'ik', 'ido':'io', 'isl':'is', 'ita':'it', 'iku':'iu', \
+ 'jpn':'ja', 'jav':'jv', 'kat':'ka', 'kon':'kg', 'kik':'ki', 'kua':'kj', \
+ 'kaz':'kk', 'kal':'kl', 'khm':'km', 'kan':'kn', 'kor':'ko', 'kau':'kr', \
+ 'kas':'ks', 'kur':'ku', 'kom':'kv', 'cor':'kw', 'kir':'ky', 'lat':'la', \
+ 'ltz':'lb', 'lug':'lg', 'lim':'li', 'lin':'ln', 'lao':'lo', 'lit':'lt', \
+ 'lub':'lu', 'lav':'lv', 'mlg':'mg', 'mah':'mh', 'mri':'mi', 'mkd':'mk', \
+ 'mal':'ml', 'mon':'mn', 'mar':'mr', 'msa':'ms', 'mlt':'mt', 'mya':'my', \
+ 'nau':'na', 'nob':'nb', 'nde':'nd', 'nep':'ne', 'ndo':'ng', 'nld':'nl', \
+ 'nno':'nn', 'nor':'no', 'nbl':'nr', 'nav':'nv', 'nya':'ny', 'oci':'oc', \
+ 'oji':'oj', 'orm':'om', 'ori':'or', 'oss':'os', 'pan':'pa', 'pli':'pi', \
+ 'pol':'pl', 'pus':'ps', 'por':'pt', 'que':'qu', 'roh':'rm', 'run':'rn', \
+ 'ron':'ro', 'rus':'ru', 'kin':'rw', 'san':'sa', 'srd':'sc', 'snd':'sd', \
+ 'sme':'se', 'sag':'sg', 'sin':'si', 'slk':'sk', 'slv':'sl', 'smo':'sm', \
+ 'sna':'sn', 'som':'so', 'sqi':'sq', 'srp':'sr', 'ssw':'ss', 'sot':'st', \
+ 'sun':'su', 'swe':'sv', 'swa':'sw', 'tam':'ta', 'tel':'te', 'tgk':'tg', \
+ 'tha':'th', 'tir':'ti', 'tuk':'tk', 'tgl':'tl', 'tsn':'tn', 'ton':'to', \
+ 'tur':'tr', 'tso':'ts', 'tat':'tt', 'twi':'tw', 'tah':'ty', 'uig':'ug', \
+ 'ukr':'uk', 'urd':'ur', 'uzb':'uz', 'ven':'ve', 'vie':'vi', 'vol':'vo', \
+ 'wln':'wa', 'wol':'wo', 'xho':'xh', 'yid':'yi', 'yor':'yo', 'zha':'za', \
+ 'zho':'zh', 'zul':'zu'}
+
+## Convert a python unicode string to a normal string
+#
+# Convert a python unicode string to a normal string
+# UniToStr(u'I am a string') is 'I am a string'
+#
+# @param Uni: The python unicode string
+#
+# @retval: The formatted normal string
+#
+def UniToStr(Uni):
+ return repr(Uni)[2:-1]
+
+## Convert a unicode string to a Hex list
+#
+# Convert a unicode string to a Hex list
+# UniToHexList('ABC') is ['0x41', '0x00', '0x42', '0x00', '0x43', '0x00']
+#
+# @param Uni: The python unicode string
+#
+# @retval List: The formatted hex list
+#
+def UniToHexList(Uni):
+ List = []
+ for Item in Uni:
+ Temp = '%04X' % ord(Item)
+ List.append('0x' + Temp[2:4])
+ List.append('0x' + Temp[0:2])
+ return List
+
+## Convert special unicode characters
+#
+# Convert special characters to (c), (r) and (tm).
+#
+# @param Uni: The python unicode string
+#
+# @retval NewUni: The converted unicode string
+#
+def ConvertSpecialUnicodes(Uni):
+ NewUni = Uni
+ NewUni = NewUni.replace(u'\u00A9', '(c)')
+ NewUni = NewUni.replace(u'\u00AE', '(r)')
+ NewUni = NewUni.replace(u'\u2122', '(tm)')
+ return NewUni
+
+## GetLanguageCode1766
+#
+# Check the language code read from .UNI file and convert RFC 4646 codes to RFC 1766 codes
+# RFC 1766 language codes supported in compatiblity mode
+# RFC 4646 language codes supported in native mode
+#
+# @param LangName: Language codes read from .UNI file
+#
+# @retval LangName: Valid lanugage code in RFC 1766 format or None
+#
+def GetLanguageCode1766(LangName, File=None):
+ length = len(LangName)
+ if length == 2:
+ if LangName.isalpha():
+ for Key in gLANG_CONV_TABLE.keys():
+ if gLANG_CONV_TABLE.get(Key) == LangName.lower():
+ return Key
+ elif length == 3:
+ if LangName.isalpha() and gLANG_CONV_TABLE.get(LangName.lower()):
+ return LangName
+ else:
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FORMAT_INVALID,
+ "Invalid RFC 1766 language code : %s" % LangName,
+ File)
+ elif length == 5:
+ if LangName[0:2].isalpha() and LangName[2] == '-':
+ for Key in gLANG_CONV_TABLE.keys():
+ if gLANG_CONV_TABLE.get(Key) == LangName[0:2].lower():
+ return Key
+ elif length >= 6:
+ if LangName[0:2].isalpha() and LangName[2] == '-':
+ for Key in gLANG_CONV_TABLE.keys():
+ if gLANG_CONV_TABLE.get(Key) == LangName[0:2].lower():
+ return Key
+ if LangName[0:3].isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) == None and LangName[3] == '-':
+ for Key in gLANG_CONV_TABLE.keys():
+ if Key == LangName[0:3].lower():
+ return Key
+
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FORMAT_INVALID,
+ "Invalid RFC 4646 language code : %s" % LangName,
+ File)
+
+## GetLanguageCode
+#
+# Check the language code read from .UNI file and convert RFC 1766 codes to RFC 4646 codes if appropriate
+# RFC 1766 language codes supported in compatiblity mode
+# RFC 4646 language codes supported in native mode
+#
+# @param LangName: Language codes read from .UNI file
+#
+# @retval LangName: Valid lanugage code in RFC 4646 format or None
+#
+def GetLanguageCode(LangName, IsCompatibleMode, File):
+ length = len(LangName)
+ if IsCompatibleMode:
+ if length == 3 and LangName.isalpha():
+ TempLangName = gLANG_CONV_TABLE.get(LangName.lower())
+ if TempLangName != None:
+ return TempLangName
+ return LangName
+ else:
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FORMAT_INVALID,
+ "Invalid RFC 1766 language code : %s" % LangName,
+ File)
+ if (LangName[0] == 'X' or LangName[0] == 'x') and LangName[1] == '-':
+ return LangName
+ if length == 2:
+ if LangName.isalpha():
+ return LangName
+ elif length == 3:
+ if LangName.isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) == None:
+ return LangName
+ elif length == 5:
+ if LangName[0:2].isalpha() and LangName[2] == '-':
+ return LangName
+ elif length >= 6:
+ if LangName[0:2].isalpha() and LangName[2] == '-':
+ return LangName
+ if LangName[0:3].isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) == None and LangName[3] == '-':
+ return LangName
+
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FORMAT_INVALID,
+ "Invalid RFC 4646 language code : %s" % LangName,
+ File)
+
+## FormatUniEntry
+#
+# Formated the entry in Uni file.
+#
+# @param StrTokenName StrTokenName.
+# @param TokenValueList A list need to be processed.
+# @param ContainerFile ContainerFile.
+#
+# @return formated entry
+def FormatUniEntry(StrTokenName, TokenValueList, ContainerFile):
+ SubContent = ''
+ PreFormatLength = 40
+ if len(StrTokenName) > PreFormatLength:
+ PreFormatLength = len(StrTokenName) + 1
+ for (Lang, Value) in TokenValueList:
+ if not Value or Lang == DT.TAB_LANGUAGE_EN_X:
+ continue
+ if Lang == '':
+ Lang = DT.TAB_LANGUAGE_EN_US
+ if Lang == 'eng':
+ Lang = DT.TAB_LANGUAGE_EN_US
+ elif len(Lang.split('-')[0]) == 3:
+ Lang = GetLanguageCode(Lang.split('-')[0], True, ContainerFile)
+ else:
+ Lang = GetLanguageCode(Lang, False, ContainerFile)
+ ValueList = Value.split('\n')
+ SubValueContent = ''
+ for SubValue in ValueList:
+ if SubValue.strip():
+ SubValueContent += \
+ ' ' * (PreFormatLength + len('#language en-US ')) + '\"%s\\n\"' % SubValue.strip() + os.linesep
+ SubValueContent = SubValueContent[(PreFormatLength + len('#language en-US ')):SubValueContent.rfind('\\n')] \
+ + '\"' + os.linesep
+ SubContent += ' '*PreFormatLength + '#language %-5s ' % Lang + SubValueContent
+ if SubContent:
+ SubContent = StrTokenName + ' '*(PreFormatLength - len(StrTokenName)) + SubContent[PreFormatLength:]
+ return SubContent
+
+
+## StringDefClassObject
+#
+# A structure for language definition
+#
+class StringDefClassObject(object):
+ def __init__(self, Name = None, Value = None, Referenced = False, Token = None, UseOtherLangDef = ''):
+ self.StringName = ''
+ self.StringNameByteList = []
+ self.StringValue = ''
+ self.StringValueByteList = ''
+ self.Token = 0
+ self.Referenced = Referenced
+ self.UseOtherLangDef = UseOtherLangDef
+ self.Length = 0
+
+ if Name != None:
+ self.StringName = Name
+ self.StringNameByteList = UniToHexList(Name)
+ if Value != None:
+ self.StringValue = Value
+ self.StringValueByteList = UniToHexList(self.StringValue)
+ self.Length = len(self.StringValueByteList)
+ if Token != None:
+ self.Token = Token
+
+ def __str__(self):
+ return repr(self.StringName) + ' ' + \
+ repr(self.Token) + ' ' + \
+ repr(self.Referenced) + ' ' + \
+ repr(self.StringValue) + ' ' + \
+ repr(self.UseOtherLangDef)
+
+ def UpdateValue(self, Value = None):
+ if Value != None:
+ if self.StringValue:
+ self.StringValue = self.StringValue + os.linesep + Value
+ else:
+ self.StringValue = Value
+ self.StringValueByteList = UniToHexList(self.StringValue)
+ self.Length = len(self.StringValueByteList)
+
+## UniFileClassObject
+#
+# A structure for .uni file definition
+#
+class UniFileClassObject(object):
+ def __init__(self, FileList = None, IsCompatibleMode = False, IncludePathList = None):
+ self.FileList = FileList
+ self.File = None
+ self.IncFileList = FileList
+ self.UniFileHeader = ''
+ self.Token = 2
+ self.LanguageDef = [] #[ [u'LanguageIdentifier', u'PrintableName'], ... ]
+ self.OrderedStringList = {} #{ u'LanguageIdentifier' : [StringDefClassObject] }
+ self.OrderedStringDict = {} #{ u'LanguageIdentifier' : {StringName:(IndexInList)} }
+ self.OrderedStringListByToken = {} #{ u'LanguageIdentifier' : {Token: StringDefClassObject} }
+ self.IsCompatibleMode = IsCompatibleMode
+ if not IncludePathList:
+ self.IncludePathList = []
+ else:
+ self.IncludePathList = IncludePathList
+ if len(self.FileList) > 0:
+ self.LoadUniFiles(FileList)
+
+ #
+ # Get Language definition
+ #
+ def GetLangDef(self, File, Line):
+ Lang = distutils.util.split_quoted((Line.split(u"//")[0]))
+ if len(Lang) != 3:
+ try:
+ FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16').read()
+ except UnicodeError, Xstr:
+ FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16_le').read()
+ except:
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FILE_OPEN_FAILURE,
+ "File read failure: %s" % str(Xstr),
+ ExtraData=File)
+ LineNo = GetLineNo(FileIn, Line, False)
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.PARSER_ERROR,
+ "Wrong language definition",
+ ExtraData="""%s\n\t*Correct format is like '#langdef en-US "English"'""" % Line,
+ File = File, Line = LineNo)
+ else:
+ LangName = GetLanguageCode(Lang[1], self.IsCompatibleMode, self.File)
+ LangPrintName = Lang[2]
+
+ IsLangInDef = False
+ for Item in self.LanguageDef:
+ if Item[0] == LangName:
+ IsLangInDef = True
+ break
+
+ if not IsLangInDef:
+ self.LanguageDef.append([LangName, LangPrintName])
+
+ #
+ # Add language string
+ #
+ self.AddStringToList(u'$LANGUAGE_NAME', LangName, LangName, 0, True, Index=0)
+ self.AddStringToList(u'$PRINTABLE_LANGUAGE_NAME', LangName, LangPrintName, 1, True, Index=1)
+
+ if not IsLangInDef:
+ #
+ # The found STRING tokens will be added into new language string list
+ # so that the unique STRING identifier is reserved for all languages in the package list.
+ #
+ FirstLangName = self.LanguageDef[0][0]
+ if LangName != FirstLangName:
+ for Index in range (2, len (self.OrderedStringList[FirstLangName])):
+ Item = self.OrderedStringList[FirstLangName][Index]
+ if Item.UseOtherLangDef != '':
+ OtherLang = Item.UseOtherLangDef
+ else:
+ OtherLang = FirstLangName
+ self.OrderedStringList[LangName].append (StringDefClassObject(Item.StringName,
+ '',
+ Item.Referenced,
+ Item.Token,
+ OtherLang))
+ self.OrderedStringDict[LangName][Item.StringName] = len(self.OrderedStringList[LangName]) - 1
+ return True
+
+ #
+ # Get String name and value
+ #
+ def GetStringObject(self, Item):
+ Language = ''
+ Value = ''
+
+ Name = Item.split()[1]
+ # Check the string name is the upper character
+ if Name != '':
+ MatchString = re.match('[A-Z0-9_]+', Name, re.UNICODE)
+ if MatchString == None or MatchString.end(0) != len(Name):
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FORMAT_INVALID,
+ 'The string token name %s in UNI file %s must be upper case character.' %(Name, self.File))
+ LanguageList = Item.split(u'#language ')
+ for IndexI in range(len(LanguageList)):
+ if IndexI == 0:
+ continue
+ else:
+ Language = LanguageList[IndexI].split()[0]
+ #.replace(u'\r\n', u'')
+ Value = \
+ LanguageList[IndexI][LanguageList[IndexI].find(u'\"') + len(u'\"') : LanguageList[IndexI].rfind(u'\"')]
+ Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File)
+ self.AddStringToList(Name, Language, Value)
+
+ #
+ # Get include file list and load them
+ #
+ def GetIncludeFile(self, Item, Dir = None):
+ if Dir:
+ pass
+ FileName = Item[Item.find(u'!include ') + len(u'!include ') :Item.find(u' ', len(u'!include '))][1:-1]
+ self.LoadUniFile(FileName)
+
+ #
+ # Pre-process before parse .uni file
+ #
+ def PreProcess(self, File, IsIncludeFile=False):
+ if not os.path.exists(File.Path) or not os.path.isfile(File.Path):
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FILE_NOT_FOUND,
+ ExtraData=File.Path)
+
+ try:
+ FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16').readlines()
+ except UnicodeError:
+ FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16_le').readlines()
+ except:
+ EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=File.Path)
+
+
+ #
+ # get the file header
+ #
+ Lines = []
+ HeaderStart = False
+ HeaderEnd = False
+ if not self.UniFileHeader:
+ FirstGenHeader = True
+ else:
+ FirstGenHeader = False
+ for Line in FileIn:
+ Line = Line.strip()
+ if Line == u'':
+ continue
+ if Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and (Line.find(DT.TAB_HEADER_COMMENT) > -1) \
+ and not HeaderEnd and not HeaderStart:
+ HeaderStart = True
+ if not Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and HeaderStart and not HeaderEnd:
+ HeaderEnd = True
+ if Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and HeaderStart and not HeaderEnd and FirstGenHeader:
+ self.UniFileHeader += Line + os.linesep
+ continue
+
+ #
+ # Use unique identifier
+ #
+ FindFlag = -1
+ LineCount = 0
+ MultiLineFeedExits = False
+ #
+ # 0: initial value
+ # 1: signle String entry exist
+ # 2: line feed exist under the some signle String entry
+ #
+ StringEntryExistsFlag = 0
+ for Line in FileIn:
+ Line = FileIn[LineCount]
+ LineCount += 1
+ Line = Line.strip()
+ #
+ # Ignore comment line and empty line
+ #
+ if Line == u'' or Line.startswith(u'//'):
+ #
+ # Change the single line String entry flag status
+ #
+ if StringEntryExistsFlag == 1:
+ StringEntryExistsFlag = 2
+ #
+ # If the '#string' line and the '#language' line are not in the same line,
+ # there should be only one line feed character betwwen them
+ #
+ if MultiLineFeedExits:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+ continue
+
+ MultiLineFeedExits = False
+ #
+ # Process comment embeded in string define lines
+ #
+ FindFlag = Line.find(u'//')
+ if FindFlag != -1 and Line.find(u'//') < Line.find(u'"'):
+ Line = Line.replace(Line[FindFlag:], u' ')
+ if FileIn[LineCount].strip().startswith('#language'):
+ Line = Line + FileIn[LineCount]
+ FileIn[LineCount-1] = Line
+ FileIn[LineCount] = os.linesep
+ LineCount -= 1
+ for Index in xrange (LineCount + 1, len (FileIn) - 1):
+ if (Index == len(FileIn) -1):
+ FileIn[Index] = os.linesep
+ else:
+ FileIn[Index] = FileIn[Index + 1]
+ continue
+ CommIndex = GetCharIndexOutStr(u'/', Line)
+ if CommIndex > -1:
+ if (len(Line) - 1) > CommIndex:
+ if Line[CommIndex+1] == u'/':
+ Line = Line[:CommIndex].strip()
+ else:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+ else:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+
+ Line = Line.replace(UNICODE_WIDE_CHAR, WIDE_CHAR)
+ Line = Line.replace(UNICODE_NARROW_CHAR, NARROW_CHAR)
+ Line = Line.replace(UNICODE_NON_BREAKING_CHAR, NON_BREAKING_CHAR)
+
+ Line = Line.replace(u'\\\\', u'\u0006')
+ Line = Line.replace(u'\\r\\n', CR + LF)
+ Line = Line.replace(u'\\n', CR + LF)
+ Line = Line.replace(u'\\r', CR)
+ Line = Line.replace(u'\\t', u'\t')
+ Line = Line.replace(u'''\"''', u'''"''')
+ Line = Line.replace(u'\t', u' ')
+ Line = Line.replace(u'\u0006', u'\\')
+
+ IncList = gINCLUDE_PATTERN.findall(Line)
+ if len(IncList) == 1:
+ for Dir in [File.Dir] + self.IncludePathList:
+ IncFile = PathClass(str(IncList[0]), Dir)
+ self.IncFileList.append(IncFile)
+ if os.path.isfile(IncFile.Path):
+ Lines.extend(self.PreProcess(IncFile, True))
+ break
+ else:
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FILE_NOT_FOUND,
+ Message="Cannot find include file",
+ ExtraData=str(IncList[0]))
+ continue
+
+ #
+ # Between Name entry and Language entry can not contain line feed
+ #
+ if Line.startswith(u'#string') and Line.find(u'#language') == -1:
+ MultiLineFeedExits = True
+
+ if Line.startswith(u'#string') and Line.find(u'#language') > 0 and Line.find(u'"') < 0:
+ MultiLineFeedExits = True
+
+ #
+ # Between Language entry and String entry can not contain line feed
+ #
+ if Line.startswith(u'#language') and len(Line.split()) == 2:
+ MultiLineFeedExits = True
+
+ #
+ # Between two String entry, can not contain line feed
+ #
+ if Line.startswith(u'"'):
+ if StringEntryExistsFlag == 2:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,
+ Message=ST.ERR_UNIPARSE_LINEFEED_UP_EXIST % Line, ExtraData=File.Path)
+
+ StringEntryExistsFlag = 1
+ if not Line.endswith('"'):
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+ elif Line.startswith(u'#language'):
+ if StringEntryExistsFlag == 2:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,
+ Message=ST.ERR_UNIPARSE_LINEFEED_UP_EXIST % Line, ExtraData=File.Path)
+ StringEntryExistsFlag = 0
+ else:
+ StringEntryExistsFlag = 0
+
+ Lines.append(Line)
+
+ #
+ # Convert string def format as below
+ #
+ # #string MY_STRING_1
+ # #language eng
+ # "My first English string line 1"
+ # "My first English string line 2"
+ # #string MY_STRING_1
+ # #language spa
+ # "Mi segunda secuencia 1"
+ # "Mi segunda secuencia 2"
+ #
+
+ if not IsIncludeFile and not Lines:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_NO_SECTION_EXIST, \
+ ExtraData=File.Path)
+
+ NewLines = []
+ StrName = u''
+ ExistStrNameList = []
+ for Line in Lines:
+ if StrName and not StrName.split()[1].startswith(DT.TAB_STR_TOKENCNAME + DT.TAB_UNDERLINE_SPLIT):
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \
+ ExtraData=File.Path)
+
+ if StrName and len(StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)) == 4:
+ StringTokenList = StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)
+ if (StringTokenList[3].upper() in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP] and \
+ StringTokenList[3] not in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP]) or \
+ (StringTokenList[2].upper() == DT.TAB_STR_TOKENERR and StringTokenList[2] != DT.TAB_STR_TOKENERR):
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_STRTOKEN_FORMAT_ERROR % StrName.split()[1], \
+ ExtraData=File.Path)
+
+ if Line.count(u'#language') > 1:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_SEP_LANGENTRY_LINE % Line, \
+ ExtraData=File.Path)
+
+ if Line.startswith(u'//'):
+ continue
+ elif Line.startswith(u'#langdef'):
+ if len(Line.split()) == 2:
+ NewLines.append(Line)
+ continue
+ elif len(Line.split()) > 2 and Line.find(u'"') > 0:
+ NewLines.append(Line[:Line.find(u'"')].strip())
+ NewLines.append(Line[Line.find(u'"'):])
+ else:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+ elif Line.startswith(u'#string'):
+ if len(Line.split()) == 2:
+ StrName = Line
+ if StrName:
+ if StrName.split()[1] not in ExistStrNameList:
+ ExistStrNameList.append(StrName.split()[1].strip())
+ elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \
+ DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \
+ DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \
+ DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \
+ ExtraData=File.Path)
+ continue
+ elif len(Line.split()) == 4 and Line.find(u'#language') > 0:
+ if Line[Line.find(u'#language')-1] != ' ' or \
+ Line[Line.find(u'#language')+len(u'#language')] != u' ':
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+
+ if Line.find(u'"') > 0:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+
+ StrName = Line.split()[0] + u' ' + Line.split()[1]
+ if StrName:
+ if StrName.split()[1] not in ExistStrNameList:
+ ExistStrNameList.append(StrName.split()[1].strip())
+ elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \
+ DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \
+ DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \
+ DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \
+ ExtraData=File.Path)
+ if IsIncludeFile:
+ if StrName not in NewLines:
+ NewLines.append((Line[:Line.find(u'#language')]).strip())
+ else:
+ NewLines.append((Line[:Line.find(u'#language')]).strip())
+ NewLines.append((Line[Line.find(u'#language'):]).strip())
+ elif len(Line.split()) > 4 and Line.find(u'#language') > 0 and Line.find(u'"') > 0:
+ if Line[Line.find(u'#language')-1] != u' ' or \
+ Line[Line.find(u'#language')+len(u'#language')] != u' ':
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+
+ if Line[Line.find(u'"')-1] != u' ':
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+
+ StrName = Line.split()[0] + u' ' + Line.split()[1]
+ if StrName:
+ if StrName.split()[1] not in ExistStrNameList:
+ ExistStrNameList.append(StrName.split()[1].strip())
+ elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \
+ DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \
+ DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \
+ DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \
+ ExtraData=File.Path)
+ if IsIncludeFile:
+ if StrName not in NewLines:
+ NewLines.append((Line[:Line.find(u'#language')]).strip())
+ else:
+ NewLines.append((Line[:Line.find(u'#language')]).strip())
+ NewLines.append((Line[Line.find(u'#language'):Line.find(u'"')]).strip())
+ NewLines.append((Line[Line.find(u'"'):]).strip())
+ else:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+ elif Line.startswith(u'#language'):
+ if len(Line.split()) == 2:
+ if IsIncludeFile:
+ if StrName not in NewLines:
+ NewLines.append(StrName)
+ else:
+ NewLines.append(StrName)
+ NewLines.append(Line)
+ elif len(Line.split()) > 2 and Line.find(u'"') > 0:
+ if IsIncludeFile:
+ if StrName not in NewLines:
+ NewLines.append(StrName)
+ else:
+ NewLines.append(StrName)
+ NewLines.append((Line[:Line.find(u'"')]).strip())
+ NewLines.append((Line[Line.find(u'"'):]).strip())
+ else:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+ elif Line.startswith(u'"'):
+ if u'#string' in Line or u'#language' in Line:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+ NewLines.append(Line)
+ else:
+ print Line
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)
+
+ if StrName and not StrName.split()[1].startswith(u'STR_'):
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \
+ ExtraData=File.Path)
+
+ if StrName and not NewLines:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNI_MISS_LANGENTRY % StrName, \
+ ExtraData=File.Path)
+
+ #
+ # Check Abstract, Description, BinaryAbstract and BinaryDescription order,
+ # should be Abstract, Description, BinaryAbstract, BinaryDesctiption
+ AbstractPosition = -1
+ DescriptionPosition = -1
+ BinaryAbstractPosition = -1
+ BinaryDescriptionPosition = -1
+ for StrName in ExistStrNameList:
+ if DT.TAB_HEADER_ABSTRACT.upper() in StrName:
+ if 'BINARY' in StrName:
+ BinaryAbstractPosition = ExistStrNameList.index(StrName)
+ else:
+ AbstractPosition = ExistStrNameList.index(StrName)
+ if DT.TAB_HEADER_DESCRIPTION.upper() in StrName:
+ if 'BINARY' in StrName:
+ BinaryDescriptionPosition = ExistStrNameList.index(StrName)
+ else:
+ DescriptionPosition = ExistStrNameList.index(StrName)
+
+ OrderList = sorted([AbstractPosition, DescriptionPosition])
+ BinaryOrderList = sorted([BinaryAbstractPosition, BinaryDescriptionPosition])
+ Min = OrderList[0]
+ Max = OrderList[1]
+ BinaryMin = BinaryOrderList[0]
+ BinaryMax = BinaryOrderList[1]
+ if BinaryDescriptionPosition > -1:
+ if not(BinaryDescriptionPosition == BinaryMax and BinaryAbstractPosition == BinaryMin and \
+ BinaryMax > Max):
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \
+ ExtraData=File.Path)
+ elif BinaryAbstractPosition > -1:
+ if not(BinaryAbstractPosition > Max):
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \
+ ExtraData=File.Path)
+
+ if DescriptionPosition > -1:
+ if not(DescriptionPosition == Max and AbstractPosition == Min and \
+ DescriptionPosition > AbstractPosition):
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \
+ Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \
+ ExtraData=File.Path)
+
+ if not self.UniFileHeader:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,
+ Message = ST.ERR_NO_SOURCE_HEADER,
+ ExtraData=File.Path)
+
+ return NewLines
+
+ #
+ # Load a .uni file
+ #
+ def LoadUniFile(self, File = None):
+ if File == None:
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.PARSER_ERROR,
+ Message='No unicode file is given',
+ ExtraData=File.Path)
+
+ self.File = File
+
+ #
+ # Process special char in file
+ #
+ Lines = self.PreProcess(File)
+
+ #
+ # Get Unicode Information
+ #
+ for IndexI in range(len(Lines)):
+ Line = Lines[IndexI]
+ if (IndexI + 1) < len(Lines):
+ SecondLine = Lines[IndexI + 1]
+ if (IndexI + 2) < len(Lines):
+ ThirdLine = Lines[IndexI + 2]
+
+ #
+ # Get Language def information
+ #
+ if Line.find(u'#langdef ') >= 0:
+ self.GetLangDef(File, Line + u' ' + SecondLine)
+ continue
+
+ Name = ''
+ Language = ''
+ Value = ''
+ CombineToken = False
+ #
+ # Get string def information format as below
+ #
+ # #string MY_STRING_1
+ # #language eng
+ # "My first English string line 1"
+ # "My first English string line 2"
+ # #string MY_STRING_1
+ # #language spa
+ # "Mi segunda secuencia 1"
+ # "Mi segunda secuencia 2"
+ #
+ if Line.find(u'#string ') >= 0 and Line.find(u'#language ') < 0 and \
+ SecondLine.find(u'#string ') < 0 and SecondLine.find(u'#language ') >= 0 and \
+ ThirdLine.find(u'#string ') < 0 and ThirdLine.find(u'#language ') < 0:
+ if Line.find('"') > 0 or SecondLine.find('"') > 0:
+ EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,
+ Message=ST.ERR_UNIPARSE_DBLQUOTE_UNMATCHED,
+ ExtraData=File.Path)
+
+ Name = Line[Line.find(u'#string ') + len(u'#string ') : ].strip(' ')
+ Language = SecondLine[SecondLine.find(u'#language ') + len(u'#language ') : ].strip(' ')
+ for IndexJ in range(IndexI + 2, len(Lines)):
+ if Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') < 0 and \
+ Lines[IndexJ].strip().startswith(u'"') and Lines[IndexJ].strip().endswith(u'"'):
+ if Lines[IndexJ][-2] == ' ':
+ CombineToken = True
+ if CombineToken:
+ if Lines[IndexJ].strip()[1:-1].strip():
+ Value = Value + Lines[IndexJ].strip()[1:-1].rstrip() + ' '
+ else:
+ Value = Value + Lines[IndexJ].strip()[1:-1]
+ CombineToken = False
+ else:
+ Value = Value + Lines[IndexJ].strip()[1:-1] + os.linesep
+ else:
+ IndexI = IndexJ
+ break
+ if Value.endswith(os.linesep):
+ Value = Value[: Value.rfind(os.linesep)]
+ Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File)
+ self.AddStringToList(Name, Language, Value)
+ continue
+
+ #
+ # Load multiple .uni files
+ #
+ def LoadUniFiles(self, FileList):
+ if len(FileList) > 0:
+ for File in FileList:
+ FilePath = File.Path.strip()
+ if FilePath.endswith('.uni') or FilePath.endswith('.UNI') or FilePath.endswith('.Uni'):
+ self.LoadUniFile(File)
+
+ #
+ # Add a string to list
+ #
+ def AddStringToList(self, Name, Language, Value, Token = 0, Referenced = False, UseOtherLangDef = '', Index = -1):
+ for LangNameItem in self.LanguageDef:
+ if Language == LangNameItem[0]:
+ break
+
+ if Language not in self.OrderedStringList:
+ self.OrderedStringList[Language] = []
+ self.OrderedStringDict[Language] = {}
+
+ IsAdded = True
+ if Name in self.OrderedStringDict[Language]:
+ IsAdded = False
+ if Value != None:
+ ItemIndexInList = self.OrderedStringDict[Language][Name]
+ Item = self.OrderedStringList[Language][ItemIndexInList]
+ Item.UpdateValue(Value)
+ Item.UseOtherLangDef = ''
+
+ if IsAdded:
+ Token = len(self.OrderedStringList[Language])
+ if Index == -1:
+ self.OrderedStringList[Language].append(StringDefClassObject(Name,
+ Value,
+ Referenced,
+ Token,
+ UseOtherLangDef))
+ self.OrderedStringDict[Language][Name] = Token
+ for LangName in self.LanguageDef:
+ #
+ # New STRING token will be added into all language string lists.
+ # so that the unique STRING identifier is reserved for all languages in the package list.
+ #
+ if LangName[0] != Language:
+ if UseOtherLangDef != '':
+ OtherLangDef = UseOtherLangDef
+ else:
+ OtherLangDef = Language
+ self.OrderedStringList[LangName[0]].append(StringDefClassObject(Name,
+ '',
+ Referenced,
+ Token,
+ OtherLangDef))
+ self.OrderedStringDict[LangName[0]][Name] = len(self.OrderedStringList[LangName[0]]) - 1
+ else:
+ self.OrderedStringList[Language].insert(Index, StringDefClassObject(Name,
+ Value,
+ Referenced,
+ Token,
+ UseOtherLangDef))
+ self.OrderedStringDict[Language][Name] = Index
+
+ #
+ # Set the string as referenced
+ #
+ def SetStringReferenced(self, Name):
+ #
+ # String stoken are added in the same order in all language string lists.
+ # So, only update the status of string stoken in first language string list.
+ #
+ Lang = self.LanguageDef[0][0]
+ if Name in self.OrderedStringDict[Lang]:
+ ItemIndexInList = self.OrderedStringDict[Lang][Name]
+ Item = self.OrderedStringList[Lang][ItemIndexInList]
+ Item.Referenced = True
+
+ #
+ # Search the string in language definition by Name
+ #
+ def FindStringValue(self, Name, Lang):
+ if Name in self.OrderedStringDict[Lang]:
+ ItemIndexInList = self.OrderedStringDict[Lang][Name]
+ return self.OrderedStringList[Lang][ItemIndexInList]
+
+ return None
+
+ #
+ # Search the string in language definition by Token
+ #
+ def FindByToken(self, Token, Lang):
+ for Item in self.OrderedStringList[Lang]:
+ if Item.Token == Token:
+ return Item
+
+ return None
+
+ #
+ # Re-order strings and re-generate tokens
+ #
+ def ReToken(self):
+ if len(self.LanguageDef) == 0:
+ return None
+ #
+ # Retoken all language strings according to the status of string stoken in the first language string.
+ #
+ FirstLangName = self.LanguageDef[0][0]
+
+ # Convert the OrderedStringList to be OrderedStringListByToken in order to faciliate future search by token
+ for LangNameItem in self.LanguageDef:
+ self.OrderedStringListByToken[LangNameItem[0]] = {}
+
+ #
+ # Use small token for all referred string stoken.
+ #
+ RefToken = 0
+ for Index in range (0, len (self.OrderedStringList[FirstLangName])):
+ FirstLangItem = self.OrderedStringList[FirstLangName][Index]
+ if FirstLangItem.Referenced == True:
+ for LangNameItem in self.LanguageDef:
+ LangName = LangNameItem[0]
+ OtherLangItem = self.OrderedStringList[LangName][Index]
+ OtherLangItem.Referenced = True
+ OtherLangItem.Token = RefToken
+ self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem
+ RefToken = RefToken + 1
+
+ #
+ # Use big token for all unreferred string stoken.
+ #
+ UnRefToken = 0
+ for Index in range (0, len (self.OrderedStringList[FirstLangName])):
+ FirstLangItem = self.OrderedStringList[FirstLangName][Index]
+ if FirstLangItem.Referenced == False:
+ for LangNameItem in self.LanguageDef:
+ LangName = LangNameItem[0]
+ OtherLangItem = self.OrderedStringList[LangName][Index]
+ OtherLangItem.Token = RefToken + UnRefToken
+ self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem
+ UnRefToken = UnRefToken + 1
+
+ #
+ # Show the instance itself
+ #
+ def ShowMe(self):
+ print self.LanguageDef
+ #print self.OrderedStringList
+ for Item in self.OrderedStringList:
+ print Item
+ for Member in self.OrderedStringList[Item]:
+ print str(Member)
+
+ #
+ # Read content from '!include' UNI file
+ #
+ def ReadIncludeUNIfile(self, FilaPath):
+ if self.File:
+ pass
+
+ if not os.path.exists(FilaPath) or not os.path.isfile(FilaPath):
+ EdkLogger.Error("Unicode File Parser",
+ ToolError.FILE_NOT_FOUND,
+ ExtraData=FilaPath)
+ try:
+ FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16').readlines()
+ except UnicodeError:
+ FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16_le').readlines()
+ except:
+ EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=FilaPath)
+ return FileIn
+
diff --git a/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py b/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py
index 7029e59889..d7614b8849 100644
--- a/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py
+++ b/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py
@@ -2,7 +2,7 @@
# This is an XML API that uses a syntax similar to XPath, but it is written in
# standard python so that no extra python packages are required to use it.
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, 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
@@ -22,6 +22,7 @@ XmlRoutines
#
import xml.dom.minidom
import re
+import codecs
from Logger.ToolError import PARSER_ERROR
import Logger.Log as Logger
@@ -219,7 +220,7 @@ def XmlNodeName(Dom):
#
def XmlParseFile(FileName):
try:
- XmlFile = open(FileName)
+ XmlFile = codecs.open(FileName, 'rb')
Dom = xml.dom.minidom.parse(XmlFile)
XmlFile.close()
return Dom