summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python/UPT/Library/Misc.py
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/Python/UPT/Library/Misc.py')
-rw-r--r--BaseTools/Source/Python/UPT/Library/Misc.py1948
1 files changed, 974 insertions, 974 deletions
diff --git a/BaseTools/Source/Python/UPT/Library/Misc.py b/BaseTools/Source/Python/UPT/Library/Misc.py
index 889b777d19..750805e328 100644
--- a/BaseTools/Source/Python/UPT/Library/Misc.py
+++ b/BaseTools/Source/Python/UPT/Library/Misc.py
@@ -1,974 +1,974 @@
-## @file
-# Common routines used by all tools
-#
-# Copyright (c) 2011, 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.
-#
-
-'''
-Misc
-'''
-
-##
-# Import Modules
-#
-import os.path
-from os import access
-from os import F_OK
-from os import makedirs
-from os import getcwd
-from os import chdir
-from os import listdir
-from os import remove
-from os import rmdir
-from os import linesep
-from os import walk
-from os import environ
-import re
-from UserDict import IterableUserDict
-
-import Logger.Log as Logger
-from Logger import StringTable as ST
-from Logger import ToolError
-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.String import GetSplitValueList
-from Library.ParserValidate import IsValidHexVersion
-from Library.ParserValidate import IsValidPath
-from Object.POM.CommonObject import TextObject
-
-## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C
-# structure style
-#
-# @param Guid: The GUID string
-#
-def GuidStringToGuidStructureString(Guid):
- GuidList = Guid.split('-')
- Result = '{'
- for Index in range(0, 3, 1):
- Result = Result + '0x' + GuidList[Index] + ', '
- Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]
- for Index in range(0, 12, 2):
- Result = Result + ', 0x' + GuidList[4][Index:Index + 2]
- Result += '}}'
- return Result
-
-## Check whether GUID string is of format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
-#
-# @param GuidValue: The GUID value
-#
-def CheckGuidRegFormat(GuidValue):
- ## Regular expression used to find out register format of GUID
- #
- RegFormatGuidPattern = re.compile("^\s*([0-9a-fA-F]){8}-"
- "([0-9a-fA-F]){4}-"
- "([0-9a-fA-F]){4}-"
- "([0-9a-fA-F]){4}-"
- "([0-9a-fA-F]){12}\s*$")
-
- if RegFormatGuidPattern.match(GuidValue):
- return True
- else:
- return False
-
-
-## Convert GUID string in C structure style to
-# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
-#
-# @param GuidValue: The GUID value in C structure format
-#
-def GuidStructureStringToGuidString(GuidValue):
- GuidValueString = GuidValue.lower().replace("{", "").replace("}", "").\
- replace(" ", "").replace(";", "")
- GuidValueList = GuidValueString.split(",")
- if len(GuidValueList) != 11:
- return ''
- try:
- return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
- int(GuidValueList[0], 16),
- int(GuidValueList[1], 16),
- int(GuidValueList[2], 16),
- int(GuidValueList[3], 16),
- int(GuidValueList[4], 16),
- int(GuidValueList[5], 16),
- int(GuidValueList[6], 16),
- int(GuidValueList[7], 16),
- int(GuidValueList[8], 16),
- int(GuidValueList[9], 16),
- int(GuidValueList[10], 16)
- )
- except BaseException:
- return ''
-
-## Create directories
-#
-# @param Directory: The directory name
-#
-def CreateDirectory(Directory):
- if Directory == None or Directory.strip() == "":
- return True
- try:
- if not access(Directory, F_OK):
- makedirs(Directory)
- except BaseException:
- return False
- return True
-
-## Remove directories, including files and sub-directories in it
-#
-# @param Directory: The directory name
-#
-def RemoveDirectory(Directory, Recursively=False):
- if Directory == None or Directory.strip() == "" or not \
- os.path.exists(Directory):
- return
- if Recursively:
- CurrentDirectory = getcwd()
- chdir(Directory)
- for File in listdir("."):
- if os.path.isdir(File):
- RemoveDirectory(File, Recursively)
- else:
- remove(File)
- chdir(CurrentDirectory)
- rmdir(Directory)
-
-## Store content in file
-#
-# This method is used to save file only when its content is changed. This is
-# quite useful for "make" system to decide what will be re-built and what
-# won't.
-#
-# @param File: The path of file
-# @param Content: The new content of the file
-# @param IsBinaryFile: The flag indicating if the file is binary file
-# or not
-#
-def SaveFileOnChange(File, Content, IsBinaryFile=True):
- if not IsBinaryFile:
- Content = Content.replace("\n", linesep)
-
- if os.path.exists(File):
- try:
- if Content == open(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.write(Content)
- FileFd.close()
- except BaseException:
- Logger.Error(None, ToolError.FILE_CREATE_FAILURE, ExtraData=File)
-
- return True
-
-## Get all files of a directory
-#
-# @param Root: Root dir
-# @param SkipList : The files need be skipped
-#
-def GetFiles(Root, SkipList=None, FullPath=True):
- OriPath = os.path.normpath(Root)
- FileList = []
- for Root, Dirs, Files in walk(Root):
- if SkipList:
- for Item in SkipList:
- if Item in Dirs:
- Dirs.remove(Item)
- for Dir in Dirs:
- if Dir.startswith('.'):
- Dirs.remove(Dir)
-
- for File in Files:
- if File.startswith('.'):
- continue
- File = os.path.normpath(os.path.join(Root, File))
- if not FullPath:
- File = File[len(OriPath) + 1:]
- FileList.append(File)
-
- return FileList
-
-## Get all non-metadata files of a directory
-#
-# @param Root: Root Dir
-# @param SkipList : List of path need be skipped
-# @param FullPath: True if the returned file should be full path
-# @param PrefixPath: the path that need to be added to the files found
-# @return: the list of files found
-#
-def GetNonMetaDataFiles(Root, SkipList, FullPath, PrefixPath):
- FileList = GetFiles(Root, SkipList, FullPath)
- NewFileList = []
- for File in FileList:
- ExtName = os.path.splitext(File)[1]
- #
- # skip '.dec', '.inf', '.dsc', '.fdf' files
- #
- if ExtName.lower() not in ['.dec', '.inf', '.dsc', '.fdf']:
- NewFileList.append(os.path.normpath(os.path.join(PrefixPath, File)))
-
- return NewFileList
-
-## Check if given file exists or not
-#
-# @param File: File name or path to be checked
-# @param Dir: The directory the file is relative to
-#
-def ValidFile(File, Ext=None):
- File = File.replace('\\', '/')
- if Ext != None:
- FileExt = os.path.splitext(File)[1]
- if FileExt.lower() != Ext.lower():
- return False
- if not os.path.exists(File):
- return False
- return True
-
-## RealPath
-#
-# @param File: File name or path to be checked
-# @param Dir: The directory the file is relative to
-# @param OverrideDir: The override directory
-#
-def RealPath(File, Dir='', OverrideDir=''):
- NewFile = os.path.normpath(os.path.join(Dir, File))
- NewFile = GlobalData.gALL_FILES[NewFile]
- if not NewFile and OverrideDir:
- NewFile = os.path.normpath(os.path.join(OverrideDir, File))
- NewFile = GlobalData.gALL_FILES[NewFile]
- return NewFile
-
-## RealPath2
-#
-# @param File: File name or path to be checked
-# @param Dir: The directory the file is relative to
-# @param OverrideDir: The override directory
-#
-def RealPath2(File, Dir='', OverrideDir=''):
- if OverrideDir:
- NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join\
- (OverrideDir, File))]
- if NewFile:
- if OverrideDir[-1] == os.path.sep:
- return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]
- else:
- return NewFile[len(OverrideDir) + 1:], \
- NewFile[0:len(OverrideDir)]
-
- NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join(Dir, File))]
- if NewFile:
- if Dir:
- if Dir[-1] == os.path.sep:
- return NewFile[len(Dir):], NewFile[0:len(Dir)]
- else:
- return NewFile[len(Dir) + 1:], NewFile[0:len(Dir)]
- else:
- return NewFile, ''
-
- return None, None
-
-## A dict which can access its keys and/or values orderly
-#
-# The class implements a new kind of dict which its keys or values can be
-# accessed in the order they are added into the dict. It guarantees the order
-# by making use of an internal list to keep a copy of keys.
-#
-class Sdict(IterableUserDict):
- ## Constructor
- #
- def __init__(self):
- IterableUserDict.__init__(self)
- self._key_list = []
-
- ## [] operator
- #
- def __setitem__(self, Key, Value):
- if Key not in self._key_list:
- self._key_list.append(Key)
- IterableUserDict.__setitem__(self, Key, Value)
-
- ## del operator
- #
- def __delitem__(self, Key):
- self._key_list.remove(Key)
- IterableUserDict.__delitem__(self, Key)
-
- ## used in "for k in dict" loop to ensure the correct order
- #
- def __iter__(self):
- return self.iterkeys()
-
- ## len() support
- #
- def __len__(self):
- return len(self._key_list)
-
- ## "in" test support
- #
- def __contains__(self, Key):
- return Key in self._key_list
-
- ## indexof support
- #
- def index(self, Key):
- return self._key_list.index(Key)
-
- ## insert support
- #
- def insert(self, Key, Newkey, Newvalue, Order):
- Index = self._key_list.index(Key)
- if Order == 'BEFORE':
- self._key_list.insert(Index, Newkey)
- IterableUserDict.__setitem__(self, Newkey, Newvalue)
- elif Order == 'AFTER':
- self._key_list.insert(Index + 1, Newkey)
- IterableUserDict.__setitem__(self, Newkey, Newvalue)
-
- ## append support
- #
- def append(self, Sdict2):
- for Key in Sdict2:
- if Key not in self._key_list:
- self._key_list.append(Key)
- IterableUserDict.__setitem__(self, Key, Sdict2[Key])
- ## hash key
- #
- def has_key(self, Key):
- return Key in self._key_list
-
- ## Empty the dict
- #
- def clear(self):
- self._key_list = []
- IterableUserDict.clear(self)
-
- ## Return a copy of keys
- #
- def keys(self):
- Keys = []
- for Key in self._key_list:
- Keys.append(Key)
- return Keys
-
- ## Return a copy of values
- #
- def values(self):
- Values = []
- for Key in self._key_list:
- Values.append(self[Key])
- return Values
-
- ## Return a copy of (key, value) list
- #
- def items(self):
- Items = []
- for Key in self._key_list:
- Items.append((Key, self[Key]))
- return Items
-
- ## Iteration support
- #
- def iteritems(self):
- return iter(self.items())
-
- ## Keys interation support
- #
- def iterkeys(self):
- return iter(self.keys())
-
- ## Values interation support
- #
- def itervalues(self):
- return iter(self.values())
-
- ## Return value related to a key, and remove the (key, value) from the dict
- #
- def pop(self, Key, *Dv):
- Value = None
- if Key in self._key_list:
- Value = self[Key]
- self.__delitem__(Key)
- elif len(Dv) != 0 :
- Value = Dv[0]
- return Value
-
- ## Return (key, value) pair, and remove the (key, value) from the dict
- #
- def popitem(self):
- Key = self._key_list[-1]
- Value = self[Key]
- self.__delitem__(Key)
- return Key, Value
- ## update method
- #
- def update(self, Dict=None, **Kwargs):
- if Dict != None:
- for Key1, Val1 in Dict.items():
- self[Key1] = Val1
- if len(Kwargs):
- for Key1, Val1 in Kwargs.items():
- self[Key1] = Val1
-
-## CommonPath
-#
-# @param PathList: PathList
-#
-def CommonPath(PathList):
- Path1 = min(PathList).split(os.path.sep)
- Path2 = max(PathList).split(os.path.sep)
- for Index in xrange(min(len(Path1), len(Path2))):
- if Path1[Index] != Path2[Index]:
- return os.path.sep.join(Path1[:Index])
- return os.path.sep.join(Path1)
-
-## PathClass
-#
-class PathClass(object):
- def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,
- Arch='COMMON', ToolChainFamily='', Target='', TagName='', \
- ToolCode=''):
- self.Arch = Arch
- self.File = str(File)
- if os.path.isabs(self.File):
- self.Root = ''
- self.AlterRoot = ''
- else:
- self.Root = str(Root)
- self.AlterRoot = str(AlterRoot)
-
- #
- # Remove any '.' and '..' in path
- #
- if self.Root:
- self.Path = os.path.normpath(os.path.join(self.Root, self.File))
- self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
- #
- # eliminate the side-effect of 'C:'
- #
- if self.Root[-1] == ':':
- self.Root += os.path.sep
- #
- # file path should not start with path separator
- #
- if self.Root[-1] == os.path.sep:
- self.File = self.Path[len(self.Root):]
- else:
- self.File = self.Path[len(self.Root) + 1:]
- else:
- self.Path = os.path.normpath(self.File)
-
- self.SubDir, self.Name = os.path.split(self.File)
- self.BaseName, self.Ext = os.path.splitext(self.Name)
-
- if self.Root:
- if self.SubDir:
- self.Dir = os.path.join(self.Root, self.SubDir)
- else:
- self.Dir = self.Root
- else:
- self.Dir = self.SubDir
-
- if IsBinary:
- self.Type = Type
- else:
- self.Type = self.Ext.lower()
-
- self.IsBinary = IsBinary
- self.Target = Target
- self.TagName = TagName
- self.ToolCode = ToolCode
- self.ToolChainFamily = ToolChainFamily
-
- self._Key = None
-
- ## Convert the object of this class to a string
- #
- # Convert member Path of the class to a string
- #
- def __str__(self):
- return self.Path
-
- ## Override __eq__ function
- #
- # Check whether PathClass are the same
- #
- def __eq__(self, Other):
- if type(Other) == type(self):
- return self.Path == Other.Path
- else:
- return self.Path == str(Other)
-
- ## Override __hash__ function
- #
- # Use Path as key in hash table
- #
- def __hash__(self):
- return hash(self.Path)
-
- ## _GetFileKey
- #
- def _GetFileKey(self):
- if self._Key == None:
- self._Key = self.Path.upper()
- return self._Key
- ## Validate
- #
- def Validate(self, Type='', CaseSensitive=True):
- if GlobalData.gCASE_INSENSITIVE:
- CaseSensitive = False
- if Type and Type.lower() != self.Type:
- return ToolError.FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % \
- (self.File, Type, self.Type)
-
- RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)
- if not RealRoot and not RealFile:
- RealFile = self.File
- if self.AlterRoot:
- RealFile = os.path.join(self.AlterRoot, self.File)
- elif self.Root:
- RealFile = os.path.join(self.Root, self.File)
- return ToolError.FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
-
- ErrorCode = 0
- ErrorInfo = ''
- if RealRoot != self.Root or RealFile != self.File:
- if CaseSensitive and (RealFile != self.File or \
- (RealRoot != self.Root and RealRoot != \
- self.AlterRoot)):
- ErrorCode = ToolError.FILE_CASE_MISMATCH
- ErrorInfo = self.File + '\n\t' + RealFile + \
- " [in file system]"
-
- self.SubDir, self.Name = os.path.split(RealFile)
- self.BaseName, self.Ext = os.path.splitext(self.Name)
- if self.SubDir:
- self.Dir = os.path.join(RealRoot, self.SubDir)
- else:
- self.Dir = RealRoot
- self.File = RealFile
- self.Root = RealRoot
- self.Path = os.path.join(RealRoot, RealFile)
- return ErrorCode, ErrorInfo
-
- Key = property(_GetFileKey)
-
-## Check environment variables
-#
-# Check environment variables that must be set for build. Currently they are
-#
-# 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():
- #
- # 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)
-
-## Check whether all module types are in list
-#
-# check whether all module types (SUP_MODULE_LIST) are in list
-#
-# @param ModuleList: a list of ModuleType
-#
-def IsAllModuleList(ModuleList):
- NewModuleList = [Module.upper() for Module in ModuleList]
- for Module in SUP_MODULE_LIST:
- if Module not in NewModuleList:
- return False
- else:
- return True
-
-## Dictionary that use comment(GenericComment, TailComment) as value,
-# if a new comment which key already in the dic is inserted, then the
-# comment will be merged.
-# Key is (Statement, SupArch), when TailComment is added, it will ident
-# according to Statement
-#
-class MergeCommentDict(dict):
- ## []= operator
- #
- def __setitem__(self, Key, CommentVal):
- GenericComment, TailComment = CommentVal
- if Key in self:
- OrigVal1, OrigVal2 = dict.__getitem__(self, Key)
- Statement = Key[0]
- dict.__setitem__(self, Key, (OrigVal1 + GenericComment, OrigVal2 \
- + len(Statement) * ' ' + TailComment))
- else:
- dict.__setitem__(self, Key, (GenericComment, TailComment))
-
- ## =[] operator
- #
- def __getitem__(self, Key):
- return dict.__getitem__(self, Key)
-
-
-## GenDummyHelpTextObj
-#
-# @retval HelpTxt: Generated dummy help text object
-#
-def GenDummyHelpTextObj():
- HelpTxt = TextObject()
- HelpTxt.SetLang(LANGUAGE_EN_US)
- HelpTxt.SetString(' ')
- return HelpTxt
-
-## ConvertVersionToDecimal, the minor version should be within 0 - 99
-# <HexVersion> ::= "0x" <Major> <Minor>
-# <Major> ::= (a-fA-F0-9){4}
-# <Minor> ::= (a-fA-F0-9){4}
-# <DecVersion> ::= (0-65535) ["." (0-99)]
-#
-# @param StringIn: The string contains version defined in INF file.
-# It can be Decimal or Hex
-#
-def ConvertVersionToDecimal(StringIn):
- if IsValidHexVersion(StringIn):
- Value = int(StringIn, 16)
- Major = Value >> 16
- Minor = Value & 0xFFFF
- MinorStr = str(Minor)
- if len(MinorStr) == 1:
- MinorStr = '0' + MinorStr
- return str(Major) + '.' + MinorStr
- else:
- if StringIn.find(TAB_SPLIT) != -1:
- return StringIn
- elif StringIn:
- return StringIn + '.0'
- else:
- #
- # when StringIn is '', return it directly
- #
- return StringIn
-
-## GetHelpStringByRemoveHashKey
-#
-# Remove hash key at the header of string and return the remain.
-#
-# @param String: The string need to be processed.
-#
-def GetHelpStringByRemoveHashKey(String):
- ReturnString = ''
- PattenRemoveHashKey = re.compile(r"^[#+\s]+", re.DOTALL)
- String = String.strip()
- if String == '':
- return String
-
- LineList = GetSplitValueList(String, END_OF_LINE)
- for Line in LineList:
- ValueList = PattenRemoveHashKey.split(Line)
- if len(ValueList) == 1:
- ReturnString += ValueList[0] + END_OF_LINE
- else:
- ReturnString += ValueList[1] + END_OF_LINE
-
- if ReturnString.endswith('\n') and not ReturnString.endswith('\n\n') and ReturnString != '\n':
- ReturnString = ReturnString[:-1]
-
- return ReturnString
-
-## ConvPathFromAbsToRel
-#
-# Get relative file path from absolute path.
-#
-# @param Path: The string contain file absolute path.
-# @param Root: The string contain the parent path of Path in.
-#
-#
-def ConvPathFromAbsToRel(Path, Root):
- Path = os.path.normpath(Path)
- Root = os.path.normpath(Root)
- FullPath = os.path.normpath(os.path.join(Root, Path))
-
- #
- # If Path is absolute path.
- # It should be in Root.
- #
- if os.path.isabs(Path):
- return FullPath[FullPath.find(Root) + len(Root) + 1:]
-
- else:
- return Path
-
-## ConvertPath
-#
-# Convert special characters to '_', '\' to '/'
-# return converted path: Test!1.inf -> Test_1.inf
-#
-# @param Path: Path to be converted
-#
-def ConvertPath(Path):
- RetPath = ''
- for Char in Path.strip():
- if Char.isalnum() or Char in '.-_/':
- RetPath = RetPath + Char
- elif Char == '\\':
- RetPath = RetPath + '/'
- else:
- RetPath = RetPath + '_'
- return RetPath
-
-## ConvertSpec
-#
-# during install, convert the Spec string extract from UPD into INF allowable definition,
-# the difference is period is allowed in the former (not the first letter) but not in the latter.
-# return converted Spec string
-#
-# @param SpecStr: SpecStr to be converted
-#
-def ConvertSpec(SpecStr):
- RetStr = ''
- for Char in SpecStr:
- if Char.isalnum() or Char == '_':
- RetStr = RetStr + Char
- else:
- RetStr = RetStr + '_'
-
- return RetStr
-
-
-## IsEqualList
-#
-# Judge two lists are identical(contain same item).
-# The rule is elements in List A are in List B and elements in List B are in List A.
-#
-# @param ListA, ListB Lists need to be judged.
-#
-# @return True ListA and ListB are identical
-# @return False ListA and ListB are different with each other
-#
-def IsEqualList(ListA, ListB):
- if ListA == ListB:
- return True
-
- for ItemA in ListA:
- if not ItemA in ListB:
- return False
-
- for ItemB in ListB:
- if not ItemB in ListA:
- return False
-
- return True
-
-## ConvertArchList
-#
-# Convert item in ArchList if the start character is lower case.
-# In UDP spec, Arch is only allowed as: [A-Z]([a-zA-Z0-9])*
-#
-# @param ArchList The ArchList need to be converted.
-#
-# @return NewList The ArchList been converted.
-#
-def ConvertArchList(ArchList):
- NewArchList = []
- if not ArchList:
- return NewArchList
-
- if type(ArchList) == list:
- for Arch in ArchList:
- Arch = Arch.upper()
- NewArchList.append(Arch)
- elif type(ArchList) == str:
- ArchList = ArchList.upper()
- NewArchList.append(ArchList)
-
- return NewArchList
-
-## ProcessLineExtender
-#
-# Process the LineExtender of Line in LineList.
-# If one line ends with a line extender, then it will be combined together with next line.
-#
-# @param LineList The LineList need to be processed.
-#
-# @return NewList The ArchList been processed.
-#
-def ProcessLineExtender(LineList):
- NewList = []
- Count = 0
- while Count < len(LineList):
- if LineList[Count].strip().endswith("\\") and Count + 1 < len(LineList):
- NewList.append(LineList[Count].strip()[:-2] + LineList[Count + 1])
- Count = Count + 1
- else:
- NewList.append(LineList[Count])
-
- Count = Count + 1
-
- return NewList
-
-## ProcessEdkComment
-#
-# Process EDK style comment in LineList: c style /* */ comment or cpp style // comment
-#
-#
-# @param LineList The LineList need to be processed.
-#
-# @return LineList The LineList been processed.
-# @return FirstPos Where Edk comment is first found, -1 if not found
-#
-def ProcessEdkComment(LineList):
- FindEdkBlockComment = False
- Count = 0
- StartPos = -1
- EndPos = -1
- FirstPos = -1
-
- while(Count < len(LineList)):
- Line = LineList[Count].strip()
- if Line.startswith("/*"):
- #
- # handling c style comment
- #
- StartPos = Count
- while Count < len(LineList):
- Line = LineList[Count].strip()
- if Line.endswith("*/"):
- if (Count == StartPos) and Line.strip() == '/*/':
- Count = Count + 1
- continue
- EndPos = Count
- FindEdkBlockComment = True
- break
- Count = Count + 1
-
- if FindEdkBlockComment:
- if FirstPos == -1:
- FirstPos = StartPos
- for Index in xrange(StartPos, EndPos+1):
- LineList[Index] = ''
- FindEdkBlockComment = False
- elif Line.find("//") != -1 and not Line.startswith("#"):
- #
- # handling cpp style comment
- #
- LineList[Count] = Line.replace("//", '#')
- if FirstPos == -1:
- FirstPos = Count
-
- Count = Count + 1
-
- return LineList, FirstPos
-
-## GetLibInstanceInfo
-#
-# Get the information from Library Instance INF file.
-#
-# @param string. A string start with # and followed by INF file path
-# @param WorkSpace. The WorkSpace directory used to combined with INF file path.
-#
-# @return GUID, Version
-def GetLibInstanceInfo(String, WorkSpace, LineNo):
-
- FileGuidString = ""
- VerString = ""
-
- OrignalString = String
- String = String.strip()
- if not String:
- return None, None
- #
- # Remove "#" characters at the beginning
- #
- String = GetHelpStringByRemoveHashKey(String)
- String = String.strip()
-
- #
- # Validate file name exist.
- #
- FullFileName = os.path.normpath(os.path.realpath(os.path.join(WorkSpace, String)))
- if not (ValidFile(FullFileName)):
- Logger.Error("InfParser",
- ToolError.FORMAT_INVALID,
- ST.ERR_FILELIST_EXIST % (String),
- File=GlobalData.gINF_MODULE_NAME,
- Line=LineNo,
- ExtraData=OrignalString)
-
- #
- # Validate file exist/format.
- #
- if IsValidPath(String, WorkSpace):
- IsValidFileFlag = True
- else:
- Logger.Error("InfParser",
- ToolError.FORMAT_INVALID,
- ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID % (String),
- File=GlobalData.gINF_MODULE_NAME,
- Line=LineNo,
- ExtraData=OrignalString)
- return False
- if IsValidFileFlag:
- FileLinesList = []
-
- try:
- FInputfile = open(FullFileName, "rb", 0)
- try:
- FileLinesList = FInputfile.readlines()
- except BaseException:
- Logger.Error("InfParser",
- ToolError.FILE_READ_FAILURE,
- ST.ERR_FILE_OPEN_FAILURE,
- File=FullFileName)
- finally:
- FInputfile.close()
- except BaseException:
- Logger.Error("InfParser",
- ToolError.FILE_READ_FAILURE,
- ST.ERR_FILE_OPEN_FAILURE,
- File=FullFileName)
-
- ReFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$")
- ReVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$")
-
- FileLinesList = ProcessLineExtender(FileLinesList)
-
- for Line in FileLinesList:
- if ReFileGuidPattern.match(Line):
- FileGuidString = Line
- if ReVerStringPattern.match(Line):
- VerString = Line
-
- if FileGuidString:
- FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1]
- if VerString:
- VerString = GetSplitValueList(VerString, '=', 1)[1]
-
- return FileGuidString, VerString
+## @file
+# Common routines used by all tools
+#
+# Copyright (c) 2011, 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.
+#
+
+'''
+Misc
+'''
+
+##
+# Import Modules
+#
+import os.path
+from os import access
+from os import F_OK
+from os import makedirs
+from os import getcwd
+from os import chdir
+from os import listdir
+from os import remove
+from os import rmdir
+from os import linesep
+from os import walk
+from os import environ
+import re
+from UserDict import IterableUserDict
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger import ToolError
+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.String import GetSplitValueList
+from Library.ParserValidate import IsValidHexVersion
+from Library.ParserValidate import IsValidPath
+from Object.POM.CommonObject import TextObject
+
+## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C
+# structure style
+#
+# @param Guid: The GUID string
+#
+def GuidStringToGuidStructureString(Guid):
+ GuidList = Guid.split('-')
+ Result = '{'
+ for Index in range(0, 3, 1):
+ Result = Result + '0x' + GuidList[Index] + ', '
+ Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]
+ for Index in range(0, 12, 2):
+ Result = Result + ', 0x' + GuidList[4][Index:Index + 2]
+ Result += '}}'
+ return Result
+
+## Check whether GUID string is of format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+#
+# @param GuidValue: The GUID value
+#
+def CheckGuidRegFormat(GuidValue):
+ ## Regular expression used to find out register format of GUID
+ #
+ RegFormatGuidPattern = re.compile("^\s*([0-9a-fA-F]){8}-"
+ "([0-9a-fA-F]){4}-"
+ "([0-9a-fA-F]){4}-"
+ "([0-9a-fA-F]){4}-"
+ "([0-9a-fA-F]){12}\s*$")
+
+ if RegFormatGuidPattern.match(GuidValue):
+ return True
+ else:
+ return False
+
+
+## Convert GUID string in C structure style to
+# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+#
+# @param GuidValue: The GUID value in C structure format
+#
+def GuidStructureStringToGuidString(GuidValue):
+ GuidValueString = GuidValue.lower().replace("{", "").replace("}", "").\
+ replace(" ", "").replace(";", "")
+ GuidValueList = GuidValueString.split(",")
+ if len(GuidValueList) != 11:
+ return ''
+ try:
+ return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
+ int(GuidValueList[0], 16),
+ int(GuidValueList[1], 16),
+ int(GuidValueList[2], 16),
+ int(GuidValueList[3], 16),
+ int(GuidValueList[4], 16),
+ int(GuidValueList[5], 16),
+ int(GuidValueList[6], 16),
+ int(GuidValueList[7], 16),
+ int(GuidValueList[8], 16),
+ int(GuidValueList[9], 16),
+ int(GuidValueList[10], 16)
+ )
+ except BaseException:
+ return ''
+
+## Create directories
+#
+# @param Directory: The directory name
+#
+def CreateDirectory(Directory):
+ if Directory == None or Directory.strip() == "":
+ return True
+ try:
+ if not access(Directory, F_OK):
+ makedirs(Directory)
+ except BaseException:
+ return False
+ return True
+
+## Remove directories, including files and sub-directories in it
+#
+# @param Directory: The directory name
+#
+def RemoveDirectory(Directory, Recursively=False):
+ if Directory == None or Directory.strip() == "" or not \
+ os.path.exists(Directory):
+ return
+ if Recursively:
+ CurrentDirectory = getcwd()
+ chdir(Directory)
+ for File in listdir("."):
+ if os.path.isdir(File):
+ RemoveDirectory(File, Recursively)
+ else:
+ remove(File)
+ chdir(CurrentDirectory)
+ rmdir(Directory)
+
+## Store content in file
+#
+# This method is used to save file only when its content is changed. This is
+# quite useful for "make" system to decide what will be re-built and what
+# won't.
+#
+# @param File: The path of file
+# @param Content: The new content of the file
+# @param IsBinaryFile: The flag indicating if the file is binary file
+# or not
+#
+def SaveFileOnChange(File, Content, IsBinaryFile=True):
+ if not IsBinaryFile:
+ Content = Content.replace("\n", linesep)
+
+ if os.path.exists(File):
+ try:
+ if Content == open(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.write(Content)
+ FileFd.close()
+ except BaseException:
+ Logger.Error(None, ToolError.FILE_CREATE_FAILURE, ExtraData=File)
+
+ return True
+
+## Get all files of a directory
+#
+# @param Root: Root dir
+# @param SkipList : The files need be skipped
+#
+def GetFiles(Root, SkipList=None, FullPath=True):
+ OriPath = os.path.normpath(Root)
+ FileList = []
+ for Root, Dirs, Files in walk(Root):
+ if SkipList:
+ for Item in SkipList:
+ if Item in Dirs:
+ Dirs.remove(Item)
+ for Dir in Dirs:
+ if Dir.startswith('.'):
+ Dirs.remove(Dir)
+
+ for File in Files:
+ if File.startswith('.'):
+ continue
+ File = os.path.normpath(os.path.join(Root, File))
+ if not FullPath:
+ File = File[len(OriPath) + 1:]
+ FileList.append(File)
+
+ return FileList
+
+## Get all non-metadata files of a directory
+#
+# @param Root: Root Dir
+# @param SkipList : List of path need be skipped
+# @param FullPath: True if the returned file should be full path
+# @param PrefixPath: the path that need to be added to the files found
+# @return: the list of files found
+#
+def GetNonMetaDataFiles(Root, SkipList, FullPath, PrefixPath):
+ FileList = GetFiles(Root, SkipList, FullPath)
+ NewFileList = []
+ for File in FileList:
+ ExtName = os.path.splitext(File)[1]
+ #
+ # skip '.dec', '.inf', '.dsc', '.fdf' files
+ #
+ if ExtName.lower() not in ['.dec', '.inf', '.dsc', '.fdf']:
+ NewFileList.append(os.path.normpath(os.path.join(PrefixPath, File)))
+
+ return NewFileList
+
+## Check if given file exists or not
+#
+# @param File: File name or path to be checked
+# @param Dir: The directory the file is relative to
+#
+def ValidFile(File, Ext=None):
+ File = File.replace('\\', '/')
+ if Ext != None:
+ FileExt = os.path.splitext(File)[1]
+ if FileExt.lower() != Ext.lower():
+ return False
+ if not os.path.exists(File):
+ return False
+ return True
+
+## RealPath
+#
+# @param File: File name or path to be checked
+# @param Dir: The directory the file is relative to
+# @param OverrideDir: The override directory
+#
+def RealPath(File, Dir='', OverrideDir=''):
+ NewFile = os.path.normpath(os.path.join(Dir, File))
+ NewFile = GlobalData.gALL_FILES[NewFile]
+ if not NewFile and OverrideDir:
+ NewFile = os.path.normpath(os.path.join(OverrideDir, File))
+ NewFile = GlobalData.gALL_FILES[NewFile]
+ return NewFile
+
+## RealPath2
+#
+# @param File: File name or path to be checked
+# @param Dir: The directory the file is relative to
+# @param OverrideDir: The override directory
+#
+def RealPath2(File, Dir='', OverrideDir=''):
+ if OverrideDir:
+ NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join\
+ (OverrideDir, File))]
+ if NewFile:
+ if OverrideDir[-1] == os.path.sep:
+ return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]
+ else:
+ return NewFile[len(OverrideDir) + 1:], \
+ NewFile[0:len(OverrideDir)]
+
+ NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join(Dir, File))]
+ if NewFile:
+ if Dir:
+ if Dir[-1] == os.path.sep:
+ return NewFile[len(Dir):], NewFile[0:len(Dir)]
+ else:
+ return NewFile[len(Dir) + 1:], NewFile[0:len(Dir)]
+ else:
+ return NewFile, ''
+
+ return None, None
+
+## A dict which can access its keys and/or values orderly
+#
+# The class implements a new kind of dict which its keys or values can be
+# accessed in the order they are added into the dict. It guarantees the order
+# by making use of an internal list to keep a copy of keys.
+#
+class Sdict(IterableUserDict):
+ ## Constructor
+ #
+ def __init__(self):
+ IterableUserDict.__init__(self)
+ self._key_list = []
+
+ ## [] operator
+ #
+ def __setitem__(self, Key, Value):
+ if Key not in self._key_list:
+ self._key_list.append(Key)
+ IterableUserDict.__setitem__(self, Key, Value)
+
+ ## del operator
+ #
+ def __delitem__(self, Key):
+ self._key_list.remove(Key)
+ IterableUserDict.__delitem__(self, Key)
+
+ ## used in "for k in dict" loop to ensure the correct order
+ #
+ def __iter__(self):
+ return self.iterkeys()
+
+ ## len() support
+ #
+ def __len__(self):
+ return len(self._key_list)
+
+ ## "in" test support
+ #
+ def __contains__(self, Key):
+ return Key in self._key_list
+
+ ## indexof support
+ #
+ def index(self, Key):
+ return self._key_list.index(Key)
+
+ ## insert support
+ #
+ def insert(self, Key, Newkey, Newvalue, Order):
+ Index = self._key_list.index(Key)
+ if Order == 'BEFORE':
+ self._key_list.insert(Index, Newkey)
+ IterableUserDict.__setitem__(self, Newkey, Newvalue)
+ elif Order == 'AFTER':
+ self._key_list.insert(Index + 1, Newkey)
+ IterableUserDict.__setitem__(self, Newkey, Newvalue)
+
+ ## append support
+ #
+ def append(self, Sdict2):
+ for Key in Sdict2:
+ if Key not in self._key_list:
+ self._key_list.append(Key)
+ IterableUserDict.__setitem__(self, Key, Sdict2[Key])
+ ## hash key
+ #
+ def has_key(self, Key):
+ return Key in self._key_list
+
+ ## Empty the dict
+ #
+ def clear(self):
+ self._key_list = []
+ IterableUserDict.clear(self)
+
+ ## Return a copy of keys
+ #
+ def keys(self):
+ Keys = []
+ for Key in self._key_list:
+ Keys.append(Key)
+ return Keys
+
+ ## Return a copy of values
+ #
+ def values(self):
+ Values = []
+ for Key in self._key_list:
+ Values.append(self[Key])
+ return Values
+
+ ## Return a copy of (key, value) list
+ #
+ def items(self):
+ Items = []
+ for Key in self._key_list:
+ Items.append((Key, self[Key]))
+ return Items
+
+ ## Iteration support
+ #
+ def iteritems(self):
+ return iter(self.items())
+
+ ## Keys interation support
+ #
+ def iterkeys(self):
+ return iter(self.keys())
+
+ ## Values interation support
+ #
+ def itervalues(self):
+ return iter(self.values())
+
+ ## Return value related to a key, and remove the (key, value) from the dict
+ #
+ def pop(self, Key, *Dv):
+ Value = None
+ if Key in self._key_list:
+ Value = self[Key]
+ self.__delitem__(Key)
+ elif len(Dv) != 0 :
+ Value = Dv[0]
+ return Value
+
+ ## Return (key, value) pair, and remove the (key, value) from the dict
+ #
+ def popitem(self):
+ Key = self._key_list[-1]
+ Value = self[Key]
+ self.__delitem__(Key)
+ return Key, Value
+ ## update method
+ #
+ def update(self, Dict=None, **Kwargs):
+ if Dict != None:
+ for Key1, Val1 in Dict.items():
+ self[Key1] = Val1
+ if len(Kwargs):
+ for Key1, Val1 in Kwargs.items():
+ self[Key1] = Val1
+
+## CommonPath
+#
+# @param PathList: PathList
+#
+def CommonPath(PathList):
+ Path1 = min(PathList).split(os.path.sep)
+ Path2 = max(PathList).split(os.path.sep)
+ for Index in xrange(min(len(Path1), len(Path2))):
+ if Path1[Index] != Path2[Index]:
+ return os.path.sep.join(Path1[:Index])
+ return os.path.sep.join(Path1)
+
+## PathClass
+#
+class PathClass(object):
+ def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,
+ Arch='COMMON', ToolChainFamily='', Target='', TagName='', \
+ ToolCode=''):
+ self.Arch = Arch
+ self.File = str(File)
+ if os.path.isabs(self.File):
+ self.Root = ''
+ self.AlterRoot = ''
+ else:
+ self.Root = str(Root)
+ self.AlterRoot = str(AlterRoot)
+
+ #
+ # Remove any '.' and '..' in path
+ #
+ if self.Root:
+ self.Path = os.path.normpath(os.path.join(self.Root, self.File))
+ self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
+ #
+ # eliminate the side-effect of 'C:'
+ #
+ if self.Root[-1] == ':':
+ self.Root += os.path.sep
+ #
+ # file path should not start with path separator
+ #
+ if self.Root[-1] == os.path.sep:
+ self.File = self.Path[len(self.Root):]
+ else:
+ self.File = self.Path[len(self.Root) + 1:]
+ else:
+ self.Path = os.path.normpath(self.File)
+
+ self.SubDir, self.Name = os.path.split(self.File)
+ self.BaseName, self.Ext = os.path.splitext(self.Name)
+
+ if self.Root:
+ if self.SubDir:
+ self.Dir = os.path.join(self.Root, self.SubDir)
+ else:
+ self.Dir = self.Root
+ else:
+ self.Dir = self.SubDir
+
+ if IsBinary:
+ self.Type = Type
+ else:
+ self.Type = self.Ext.lower()
+
+ self.IsBinary = IsBinary
+ self.Target = Target
+ self.TagName = TagName
+ self.ToolCode = ToolCode
+ self.ToolChainFamily = ToolChainFamily
+
+ self._Key = None
+
+ ## Convert the object of this class to a string
+ #
+ # Convert member Path of the class to a string
+ #
+ def __str__(self):
+ return self.Path
+
+ ## Override __eq__ function
+ #
+ # Check whether PathClass are the same
+ #
+ def __eq__(self, Other):
+ if type(Other) == type(self):
+ return self.Path == Other.Path
+ else:
+ return self.Path == str(Other)
+
+ ## Override __hash__ function
+ #
+ # Use Path as key in hash table
+ #
+ def __hash__(self):
+ return hash(self.Path)
+
+ ## _GetFileKey
+ #
+ def _GetFileKey(self):
+ if self._Key == None:
+ self._Key = self.Path.upper()
+ return self._Key
+ ## Validate
+ #
+ def Validate(self, Type='', CaseSensitive=True):
+ if GlobalData.gCASE_INSENSITIVE:
+ CaseSensitive = False
+ if Type and Type.lower() != self.Type:
+ return ToolError.FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % \
+ (self.File, Type, self.Type)
+
+ RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)
+ if not RealRoot and not RealFile:
+ RealFile = self.File
+ if self.AlterRoot:
+ RealFile = os.path.join(self.AlterRoot, self.File)
+ elif self.Root:
+ RealFile = os.path.join(self.Root, self.File)
+ return ToolError.FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
+
+ ErrorCode = 0
+ ErrorInfo = ''
+ if RealRoot != self.Root or RealFile != self.File:
+ if CaseSensitive and (RealFile != self.File or \
+ (RealRoot != self.Root and RealRoot != \
+ self.AlterRoot)):
+ ErrorCode = ToolError.FILE_CASE_MISMATCH
+ ErrorInfo = self.File + '\n\t' + RealFile + \
+ " [in file system]"
+
+ self.SubDir, self.Name = os.path.split(RealFile)
+ self.BaseName, self.Ext = os.path.splitext(self.Name)
+ if self.SubDir:
+ self.Dir = os.path.join(RealRoot, self.SubDir)
+ else:
+ self.Dir = RealRoot
+ self.File = RealFile
+ self.Root = RealRoot
+ self.Path = os.path.join(RealRoot, RealFile)
+ return ErrorCode, ErrorInfo
+
+ Key = property(_GetFileKey)
+
+## Check environment variables
+#
+# Check environment variables that must be set for build. Currently they are
+#
+# 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():
+ #
+ # 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)
+
+## Check whether all module types are in list
+#
+# check whether all module types (SUP_MODULE_LIST) are in list
+#
+# @param ModuleList: a list of ModuleType
+#
+def IsAllModuleList(ModuleList):
+ NewModuleList = [Module.upper() for Module in ModuleList]
+ for Module in SUP_MODULE_LIST:
+ if Module not in NewModuleList:
+ return False
+ else:
+ return True
+
+## Dictionary that use comment(GenericComment, TailComment) as value,
+# if a new comment which key already in the dic is inserted, then the
+# comment will be merged.
+# Key is (Statement, SupArch), when TailComment is added, it will ident
+# according to Statement
+#
+class MergeCommentDict(dict):
+ ## []= operator
+ #
+ def __setitem__(self, Key, CommentVal):
+ GenericComment, TailComment = CommentVal
+ if Key in self:
+ OrigVal1, OrigVal2 = dict.__getitem__(self, Key)
+ Statement = Key[0]
+ dict.__setitem__(self, Key, (OrigVal1 + GenericComment, OrigVal2 \
+ + len(Statement) * ' ' + TailComment))
+ else:
+ dict.__setitem__(self, Key, (GenericComment, TailComment))
+
+ ## =[] operator
+ #
+ def __getitem__(self, Key):
+ return dict.__getitem__(self, Key)
+
+
+## GenDummyHelpTextObj
+#
+# @retval HelpTxt: Generated dummy help text object
+#
+def GenDummyHelpTextObj():
+ HelpTxt = TextObject()
+ HelpTxt.SetLang(LANGUAGE_EN_US)
+ HelpTxt.SetString(' ')
+ return HelpTxt
+
+## ConvertVersionToDecimal, the minor version should be within 0 - 99
+# <HexVersion> ::= "0x" <Major> <Minor>
+# <Major> ::= (a-fA-F0-9){4}
+# <Minor> ::= (a-fA-F0-9){4}
+# <DecVersion> ::= (0-65535) ["." (0-99)]
+#
+# @param StringIn: The string contains version defined in INF file.
+# It can be Decimal or Hex
+#
+def ConvertVersionToDecimal(StringIn):
+ if IsValidHexVersion(StringIn):
+ Value = int(StringIn, 16)
+ Major = Value >> 16
+ Minor = Value & 0xFFFF
+ MinorStr = str(Minor)
+ if len(MinorStr) == 1:
+ MinorStr = '0' + MinorStr
+ return str(Major) + '.' + MinorStr
+ else:
+ if StringIn.find(TAB_SPLIT) != -1:
+ return StringIn
+ elif StringIn:
+ return StringIn + '.0'
+ else:
+ #
+ # when StringIn is '', return it directly
+ #
+ return StringIn
+
+## GetHelpStringByRemoveHashKey
+#
+# Remove hash key at the header of string and return the remain.
+#
+# @param String: The string need to be processed.
+#
+def GetHelpStringByRemoveHashKey(String):
+ ReturnString = ''
+ PattenRemoveHashKey = re.compile(r"^[#+\s]+", re.DOTALL)
+ String = String.strip()
+ if String == '':
+ return String
+
+ LineList = GetSplitValueList(String, END_OF_LINE)
+ for Line in LineList:
+ ValueList = PattenRemoveHashKey.split(Line)
+ if len(ValueList) == 1:
+ ReturnString += ValueList[0] + END_OF_LINE
+ else:
+ ReturnString += ValueList[1] + END_OF_LINE
+
+ if ReturnString.endswith('\n') and not ReturnString.endswith('\n\n') and ReturnString != '\n':
+ ReturnString = ReturnString[:-1]
+
+ return ReturnString
+
+## ConvPathFromAbsToRel
+#
+# Get relative file path from absolute path.
+#
+# @param Path: The string contain file absolute path.
+# @param Root: The string contain the parent path of Path in.
+#
+#
+def ConvPathFromAbsToRel(Path, Root):
+ Path = os.path.normpath(Path)
+ Root = os.path.normpath(Root)
+ FullPath = os.path.normpath(os.path.join(Root, Path))
+
+ #
+ # If Path is absolute path.
+ # It should be in Root.
+ #
+ if os.path.isabs(Path):
+ return FullPath[FullPath.find(Root) + len(Root) + 1:]
+
+ else:
+ return Path
+
+## ConvertPath
+#
+# Convert special characters to '_', '\' to '/'
+# return converted path: Test!1.inf -> Test_1.inf
+#
+# @param Path: Path to be converted
+#
+def ConvertPath(Path):
+ RetPath = ''
+ for Char in Path.strip():
+ if Char.isalnum() or Char in '.-_/':
+ RetPath = RetPath + Char
+ elif Char == '\\':
+ RetPath = RetPath + '/'
+ else:
+ RetPath = RetPath + '_'
+ return RetPath
+
+## ConvertSpec
+#
+# during install, convert the Spec string extract from UPD into INF allowable definition,
+# the difference is period is allowed in the former (not the first letter) but not in the latter.
+# return converted Spec string
+#
+# @param SpecStr: SpecStr to be converted
+#
+def ConvertSpec(SpecStr):
+ RetStr = ''
+ for Char in SpecStr:
+ if Char.isalnum() or Char == '_':
+ RetStr = RetStr + Char
+ else:
+ RetStr = RetStr + '_'
+
+ return RetStr
+
+
+## IsEqualList
+#
+# Judge two lists are identical(contain same item).
+# The rule is elements in List A are in List B and elements in List B are in List A.
+#
+# @param ListA, ListB Lists need to be judged.
+#
+# @return True ListA and ListB are identical
+# @return False ListA and ListB are different with each other
+#
+def IsEqualList(ListA, ListB):
+ if ListA == ListB:
+ return True
+
+ for ItemA in ListA:
+ if not ItemA in ListB:
+ return False
+
+ for ItemB in ListB:
+ if not ItemB in ListA:
+ return False
+
+ return True
+
+## ConvertArchList
+#
+# Convert item in ArchList if the start character is lower case.
+# In UDP spec, Arch is only allowed as: [A-Z]([a-zA-Z0-9])*
+#
+# @param ArchList The ArchList need to be converted.
+#
+# @return NewList The ArchList been converted.
+#
+def ConvertArchList(ArchList):
+ NewArchList = []
+ if not ArchList:
+ return NewArchList
+
+ if type(ArchList) == list:
+ for Arch in ArchList:
+ Arch = Arch.upper()
+ NewArchList.append(Arch)
+ elif type(ArchList) == str:
+ ArchList = ArchList.upper()
+ NewArchList.append(ArchList)
+
+ return NewArchList
+
+## ProcessLineExtender
+#
+# Process the LineExtender of Line in LineList.
+# If one line ends with a line extender, then it will be combined together with next line.
+#
+# @param LineList The LineList need to be processed.
+#
+# @return NewList The ArchList been processed.
+#
+def ProcessLineExtender(LineList):
+ NewList = []
+ Count = 0
+ while Count < len(LineList):
+ if LineList[Count].strip().endswith("\\") and Count + 1 < len(LineList):
+ NewList.append(LineList[Count].strip()[:-2] + LineList[Count + 1])
+ Count = Count + 1
+ else:
+ NewList.append(LineList[Count])
+
+ Count = Count + 1
+
+ return NewList
+
+## ProcessEdkComment
+#
+# Process EDK style comment in LineList: c style /* */ comment or cpp style // comment
+#
+#
+# @param LineList The LineList need to be processed.
+#
+# @return LineList The LineList been processed.
+# @return FirstPos Where Edk comment is first found, -1 if not found
+#
+def ProcessEdkComment(LineList):
+ FindEdkBlockComment = False
+ Count = 0
+ StartPos = -1
+ EndPos = -1
+ FirstPos = -1
+
+ while(Count < len(LineList)):
+ Line = LineList[Count].strip()
+ if Line.startswith("/*"):
+ #
+ # handling c style comment
+ #
+ StartPos = Count
+ while Count < len(LineList):
+ Line = LineList[Count].strip()
+ if Line.endswith("*/"):
+ if (Count == StartPos) and Line.strip() == '/*/':
+ Count = Count + 1
+ continue
+ EndPos = Count
+ FindEdkBlockComment = True
+ break
+ Count = Count + 1
+
+ if FindEdkBlockComment:
+ if FirstPos == -1:
+ FirstPos = StartPos
+ for Index in xrange(StartPos, EndPos+1):
+ LineList[Index] = ''
+ FindEdkBlockComment = False
+ elif Line.find("//") != -1 and not Line.startswith("#"):
+ #
+ # handling cpp style comment
+ #
+ LineList[Count] = Line.replace("//", '#')
+ if FirstPos == -1:
+ FirstPos = Count
+
+ Count = Count + 1
+
+ return LineList, FirstPos
+
+## GetLibInstanceInfo
+#
+# Get the information from Library Instance INF file.
+#
+# @param string. A string start with # and followed by INF file path
+# @param WorkSpace. The WorkSpace directory used to combined with INF file path.
+#
+# @return GUID, Version
+def GetLibInstanceInfo(String, WorkSpace, LineNo):
+
+ FileGuidString = ""
+ VerString = ""
+
+ OrignalString = String
+ String = String.strip()
+ if not String:
+ return None, None
+ #
+ # Remove "#" characters at the beginning
+ #
+ String = GetHelpStringByRemoveHashKey(String)
+ String = String.strip()
+
+ #
+ # Validate file name exist.
+ #
+ FullFileName = os.path.normpath(os.path.realpath(os.path.join(WorkSpace, String)))
+ if not (ValidFile(FullFileName)):
+ Logger.Error("InfParser",
+ ToolError.FORMAT_INVALID,
+ ST.ERR_FILELIST_EXIST % (String),
+ File=GlobalData.gINF_MODULE_NAME,
+ Line=LineNo,
+ ExtraData=OrignalString)
+
+ #
+ # Validate file exist/format.
+ #
+ if IsValidPath(String, WorkSpace):
+ IsValidFileFlag = True
+ else:
+ Logger.Error("InfParser",
+ ToolError.FORMAT_INVALID,
+ ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID % (String),
+ File=GlobalData.gINF_MODULE_NAME,
+ Line=LineNo,
+ ExtraData=OrignalString)
+ return False
+ if IsValidFileFlag:
+ FileLinesList = []
+
+ try:
+ FInputfile = open(FullFileName, "rb", 0)
+ try:
+ FileLinesList = FInputfile.readlines()
+ except BaseException:
+ Logger.Error("InfParser",
+ ToolError.FILE_READ_FAILURE,
+ ST.ERR_FILE_OPEN_FAILURE,
+ File=FullFileName)
+ finally:
+ FInputfile.close()
+ except BaseException:
+ Logger.Error("InfParser",
+ ToolError.FILE_READ_FAILURE,
+ ST.ERR_FILE_OPEN_FAILURE,
+ File=FullFileName)
+
+ ReFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$")
+ ReVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$")
+
+ FileLinesList = ProcessLineExtender(FileLinesList)
+
+ for Line in FileLinesList:
+ if ReFileGuidPattern.match(Line):
+ FileGuidString = Line
+ if ReVerStringPattern.match(Line):
+ VerString = Line
+
+ if FileGuidString:
+ FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1]
+ if VerString:
+ VerString = GetSplitValueList(VerString, '=', 1)[1]
+
+ return FileGuidString, VerString