X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FMisc.py;h=5db9405ddc06264c53a2909b3f08e25efbc29ad7;hb=2e351cbe8e190271b3716284fc1076551d005472;hp=1d62a8b56b8b55e8646acceed3601e6d45c4b7eb;hpb=a09f4c91f785e36f0987aa3a6d7656ba51e6aeda;p=mirror_edk2.git diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py index 1d62a8b56b..5db9405ddc 100644 --- a/BaseTools/Source/Python/Common/Misc.py +++ b/BaseTools/Source/Python/Common/Misc.py @@ -1,20 +1,15 @@ ## @file # Common routines used by all tools # -# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
-# 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. +# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent # ## # Import Modules # -import Common.LongFilePathOs as os +from __future__ import absolute_import + import sys import string import threading @@ -23,22 +18,24 @@ import re import pickle import array import shutil +from random import sample from struct import pack -from UserDict import IterableUserDict -from UserList import UserList +import uuid +import subprocess +from collections import OrderedDict +import Common.LongFilePathOs as os from Common import EdkLogger as EdkLogger from Common import GlobalData as GlobalData -from .DataType import * -from .BuildToolError import * +from Common.DataType import * +from Common.BuildToolError import * from CommonDataClass.DataClass import * -from .Parsing import GetSplitValueList +from Common.Parsing import GetSplitValueList from Common.LongFilePathSupport import OpenLongFilePath as open from Common.MultipleWorkspace import MultipleWorkspace as mws -import uuid from CommonDataClass.Exceptions import BadExpression from Common.caching import cached_property -import subprocess + ## Regular expression used to find out place holders in string template gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE) @@ -49,8 +46,7 @@ valuePatternGcc = re.compile('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$') pcdPatternGcc = re.compile('^([\da-fA-Fx]+) +([\da-fA-Fx]+)') secReGeneral = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE) -## Dictionary used to store file time stamp for quick re-access -gFileTimeStampCache = {} # {file path : file time stamp} +StructPattern = re.compile(r'[_a-zA-Z][0-9A-Za-z_]*$') ## Dictionary used to store dependencies of files gDependencyDatabase = {} # arch : {file path : [dependent files list]} @@ -454,21 +450,22 @@ def RemoveDirectory(Directory, Recursively=False): # @retval False If the file content is the same # def SaveFileOnChange(File, Content, IsBinaryFile=True): - if not IsBinaryFile: - Content = Content.replace("\n", os.linesep) if os.path.exists(File): - try: - if isinstance(Content, bytes): + if IsBinaryFile: + try: with open(File, "rb") as f: if Content == f.read(): return False - else: + except: + EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File) + else: + try: with open(File, "r") as f: if Content == f.read(): return False - except: - EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File) + except: + EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File) DirName = os.path.dirname(File) if not CreateDirectory(DirName): @@ -479,68 +476,21 @@ def SaveFileOnChange(File, Content, IsBinaryFile=True): if not os.access(DirName, os.W_OK): EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName) - try: - if GlobalData.gIsWindows: - try: - from .PyUtility import SaveFileToDisk - if not SaveFileToDisk(File, Content): - EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File) - except: - if isinstance(Content, bytes): - with open(File, "wb") as Fd: - Fd.write(Content) - else: - with open(File, "w") as Fd: - Fd.write(Content) - else: - if isinstance(Content, bytes): - with open(File, "wb") as Fd: - Fd.write(Content) - else: - with open(File, "w") as Fd: - Fd.write(Content) - except IOError as X: - EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X) + if IsBinaryFile: + try: + with open(File, "wb") as Fd: + Fd.write(Content) + except IOError as X: + EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X) + else: + try: + with open(File, 'w') as Fd: + Fd.write(Content) + except IOError as X: + EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X) return True -## Make a Python object persistent on file system -# -# @param Data The object to be stored in file -# @param File The path of file to store the object -# -def DataDump(Data, File): - Fd = None - try: - Fd = open(File, 'wb') - pickle.dump(Data, Fd, pickle.HIGHEST_PROTOCOL) - except: - EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False) - finally: - if Fd is not None: - Fd.close() - -## Restore a Python object from a file -# -# @param File The path of file stored the object -# -# @retval object A python object -# @retval None If failure in file operation -# -def DataRestore(File): - Data = None - Fd = None - try: - Fd = open(File, 'rb') - Data = pickle.load(Fd) - except Exception as e: - EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e))) - Data = None - finally: - if Fd is not None: - Fd.close() - return Data - ## Retrieve and cache the real path name in file system # # @param Root The root directory of path relative to @@ -620,32 +570,6 @@ def RealPath(File, Dir='', OverrideDir=''): NewFile = GlobalData.gAllFiles[NewFile] return NewFile -def RealPath2(File, Dir='', OverrideDir=''): - NewFile = None - if OverrideDir: - NewFile = GlobalData.gAllFiles[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)] - if GlobalData.gAllFiles: - NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))] - if not NewFile: - NewFile = os.path.normpath(os.path.join(Dir, File)) - if not os.path.exists(NewFile): - return None, None - 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 - ## Get GUID value from given packages # # @param CName The CName of the GUID @@ -657,50 +581,13 @@ def RealPath2(File, Dir='', OverrideDir=''): # def GuidValue(CName, PackageList, Inffile = None): for P in PackageList: - GuidKeys = P.Guids.keys() + GuidKeys = list(P.Guids.keys()) if Inffile and P._PrivateGuids: if not Inffile.startswith(P.MetaFile.Dir): GuidKeys = [x for x in P.Guids if x not in P._PrivateGuids] if CName in GuidKeys: return P.Guids[CName] return None - -## Get Protocol value from given packages -# -# @param CName The CName of the GUID -# @param PackageList List of packages looking-up in -# @param Inffile The driver file -# -# @retval GuidValue if the CName is found in any given package -# @retval None if the CName is not found in all given packages -# -def ProtocolValue(CName, PackageList, Inffile = None): - for P in PackageList: - ProtocolKeys = P.Protocols.keys() - if Inffile and P._PrivateProtocols: - if not Inffile.startswith(P.MetaFile.Dir): - ProtocolKeys = [x for x in P.Protocols if x not in P._PrivateProtocols] - if CName in ProtocolKeys: - return P.Protocols[CName] - return None - -## Get PPI value from given packages -# -# @param CName The CName of the GUID -# @param PackageList List of packages looking-up in -# @param Inffile The driver file -# -# @retval GuidValue if the CName is found in any given package -# @retval None if the CName is not found in all given packages -# -def PpiValue(CName, PackageList, Inffile = None): - for P in PackageList: - PpiKeys = P.Ppis.keys() - if Inffile and P._PrivatePpis: - if not Inffile.startswith(P.MetaFile.Dir): - PpiKeys = [x for x in P.Ppis if x not in P._PrivatePpis] - if CName in PpiKeys: - return P.Ppis[CName] return None ## A string template class @@ -796,7 +683,7 @@ class TemplateString(object): ## Constructor def __init__(self, Template=None): - self.String = '' + self.String = [] self.IsBinary = False self._Template = Template self._TemplateSectionList = self._Parse(Template) @@ -806,7 +693,7 @@ class TemplateString(object): # @retval string The string replaced # def __str__(self): - return self.String + return "".join(self.String) ## Split the template string into fragments per the ${BEGIN} and ${END} flags # @@ -854,9 +741,12 @@ class TemplateString(object): def Append(self, AppendString, Dictionary=None): if Dictionary: SectionList = self._Parse(AppendString) - self.String += "".join(S.Instantiate(Dictionary) for S in SectionList) + self.String.append( "".join(S.Instantiate(Dictionary) for S in SectionList)) else: - self.String += AppendString + if isinstance(AppendString,list): + self.String.extend(AppendString) + else: + self.String.append(AppendString) ## Replace the string template with dictionary of placeholders # @@ -879,10 +769,10 @@ class Progressor: ## Constructor # - # @param OpenMessage The string printed before progress charaters - # @param CloseMessage The string printed after progress charaters - # @param ProgressChar The charater used to indicate the progress - # @param Interval The interval in seconds between two progress charaters + # @param OpenMessage The string printed before progress characters + # @param CloseMessage The string printed after progress characters + # @param ProgressChar The character used to indicate the progress + # @param Interval The interval in seconds between two progress characters # def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0): self.PromptMessage = OpenMessage @@ -892,9 +782,9 @@ class Progressor: if Progressor._StopFlag is None: Progressor._StopFlag = threading.Event() - ## Start to print progress charater + ## Start to print progress character # - # @param OpenMessage The string printed before progress charaters + # @param OpenMessage The string printed before progress characters # def Start(self, OpenMessage=None): if OpenMessage is not None: @@ -905,9 +795,9 @@ class Progressor: Progressor._ProgressThread.setDaemon(False) Progressor._ProgressThread.start() - ## Stop printing progress charater + ## Stop printing progress character # - # @param CloseMessage The string printed after progress charaters + # @param CloseMessage The string printed after progress characters # def Stop(self, CloseMessage=None): OriginalCodaMessage = self.CodaMessage @@ -940,165 +830,6 @@ class Progressor: Progressor._ProgressThread.join() Progressor._ProgressThread = 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, sdict): - for key in sdict: - if key not in self._key_list: - self._key_list.append(key) - IterableUserDict.__setitem__(self, key, sdict[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 self.keys() - - ## Values interation support - def itervalues(self): - return 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 - - def update(self, dict=None, **kwargs): - if dict is not None: - for k, v in dict.items(): - self[k] = v - if len(kwargs): - for k, v in kwargs.items(): - self[k] = v - -## Dictionary with restricted keys -# -class rdict(dict): - ## Constructor - def __init__(self, KeyList): - for Key in KeyList: - dict.__setitem__(self, Key, "") - - ## []= operator - def __setitem__(self, key, value): - if key not in self: - EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key, - ExtraData=", ".join(dict.keys(self))) - dict.__setitem__(self, key, value) - - ## =[] operator - def __getitem__(self, key): - if key not in self: - return "" - return dict.__getitem__(self, key) - - ## del operator - def __delitem__(self, key): - EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del") - - ## Empty the dict - def clear(self): - for Key in self: - self.__setitem__(Key, "") - - ## Return value related to a key, and remove the (key, value) from the dict - def pop(self, key, *dv): - EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop") - - ## Return (key, value) pair, and remove the (key, value) from the dict - def popitem(self): - EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem") ## Dictionary using prioritized list as key # @@ -1106,7 +837,7 @@ class tdict: _ListType = type([]) _TupleType = type(()) _Wildcard = 'COMMON' - _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM'] + _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', TAB_STAR, 'PLATFORM'] def __init__(self, _Single_=False, _Level_=2): self._Level_ = _Level_ @@ -1238,24 +969,9 @@ class tdict: keys |= self.data[Key].GetKeys(KeyIndex - 1) return keys -def IsFieldValueAnArray (Value): - Value = Value.strip() - if Value.startswith(TAB_GUID) and Value.endswith(')'): - return True - if Value.startswith('L"') and Value.endswith('"') and len(list(Value[2:-1])) > 1: - return True - if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1: - return True - if Value[0] == '{' and Value[-1] == '}': - return True - if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1: - return True - if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1: - return True - return False - def AnalyzePcdExpression(Setting): - Setting = Setting.strip() + RanStr = ''.join(sample(string.ascii_letters + string.digits, 8)) + Setting = Setting.replace('\\\\', RanStr).strip() # There might be escaped quote in a string: \", \\\" , \', \\\' Data = Setting # There might be '|' in string and in ( ... | ... ), replace it with '-' @@ -1288,32 +1004,37 @@ def AnalyzePcdExpression(Setting): break FieldList.append(Setting[StartPos:Pos].strip()) StartPos = Pos + 1 - + for i, ch in enumerate(FieldList): + if RanStr in ch: + FieldList[i] = ch.replace(RanStr,'\\\\') return FieldList -def ParseDevPathValue (Value): - if '\\' in Value: - Value.replace('\\', '/').replace(' ', '') - - Cmd = 'DevicePath ' + '"' + Value + '"' - try: - p = subprocess.Popen(Cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - out, err = p.communicate() - except Exception as X: - raise BadExpression("DevicePath: %s" % (str(X)) ) - finally: - subprocess._cleanup() - p.stdout.close() - p.stderr.close() - if err: - raise BadExpression("DevicePath: %s" % str(err)) - Size = len(out.split()) - out = ','.join(out.split()) - return '{' + out + '}', Size - def ParseFieldValue (Value): + def ParseDevPathValue (Value): + if '\\' in Value: + Value.replace('\\', '/').replace(' ', '') + + Cmd = 'DevicePath ' + '"' + Value + '"' + try: + p = subprocess.Popen(Cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + out, err = p.communicate() + except Exception as X: + raise BadExpression("DevicePath: %s" % (str(X)) ) + finally: + subprocess._cleanup() + p.stdout.close() + p.stderr.close() + if err: + raise BadExpression("DevicePath: %s" % str(err)) + out = out.decode(encoding='utf-8', errors='ignore') + Size = len(out.split()) + out = ','.join(out.split()) + return '{' + out + '}', Size + + if "{CODE(" in Value: + return Value, len(Value.split(",")) if isinstance(Value, type(0)): - return Value, (Value.bit_length() + 7) / 8 + return Value, (Value.bit_length() + 7) // 8 if not isinstance(Value, type('')): raise BadExpression('Type %s is %s' %(Value, type(Value))) Value = Value.strip() @@ -1347,7 +1068,10 @@ def ParseFieldValue (Value): if Value[0] == '"' and Value[-1] == '"': Value = Value[1:-1] try: - Value = "'" + uuid.UUID(Value).get_bytes_le() + "'" + Value = str(uuid.UUID(Value).bytes_le) + if Value.startswith("b'"): + Value = Value[2:-1] + Value = "'" + Value + "'" except ValueError as Message: raise BadExpression(Message) Value, Size = ParseFieldValue(Value) @@ -1434,12 +1158,12 @@ def ParseFieldValue (Value): raise BadExpression("invalid hex value: %s" % Value) if Value == 0: return 0, 1 - return Value, (Value.bit_length() + 7) / 8 + return Value, (Value.bit_length() + 7) // 8 if Value[0].isdigit(): Value = int(Value, 10) if Value == 0: return 0, 1 - return Value, (Value.bit_length() + 7) / 8 + return Value, (Value.bit_length() + 7) // 8 if Value.lower() == 'true': return 1, 1 if Value.lower() == 'false': @@ -1480,7 +1204,7 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''): Size = '' if len(FieldList) > 1 and FieldList[1]: DataType = FieldList[1] - if FieldList[1] != TAB_VOID: + if FieldList[1] != TAB_VOID and StructPattern.match(FieldList[1]) is None: IsValid = False if len(FieldList) > 2: Size = FieldList[2] @@ -1534,8 +1258,6 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''): Offset = FieldList[2] if len(FieldList) > 3: Value = FieldList[3] - if not Value: - IsValid = False if len(FieldList) > 4: Attribute = FieldList[4] return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3 @@ -1600,9 +1322,11 @@ def CheckPcdDatum(Type, Value): return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\ ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type) elif Type in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64]: - if Value and int(Value, 0) < 0: - return False, "PCD can't be set to negative value[%s] for datum type [%s]" % (Value, Type) + if Value.startswith('0') and not Value.lower().startswith('0x') and len(Value) > 1 and Value.lstrip('0'): + Value = Value.lstrip('0') try: + if Value and int(Value, 0) < 0: + return False, "PCD can't be set to negative value[%s] for datum type [%s]" % (Value, Type) Value = int(Value, 0) if Value > MAX_VAL_TYPE[Type]: return False, "Too large PCD value[%s] for datum type [%s]" % (Value, Type) @@ -1614,35 +1338,6 @@ def CheckPcdDatum(Type, Value): return True, "" -## Split command line option string to list -# -# subprocess.Popen needs the args to be a sequence. Otherwise there's problem -# in non-windows platform to launch command -# -def SplitOption(OptionString): - OptionList = [] - LastChar = " " - OptionStart = 0 - QuotationMark = "" - for Index in range(0, len(OptionString)): - CurrentChar = OptionString[Index] - if CurrentChar in ['"', "'"]: - if QuotationMark == CurrentChar: - QuotationMark = "" - elif QuotationMark == "": - QuotationMark = CurrentChar - continue - elif QuotationMark: - continue - - if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]: - if Index > OptionStart: - OptionList.append(OptionString[OptionStart:Index - 1]) - OptionStart = Index - LastChar = CurrentChar - OptionList.append(OptionString[OptionStart:]) - return OptionList - def CommonPath(PathList): P1 = min(PathList).split(os.path.sep) P2 = max(PathList).split(os.path.sep) @@ -1651,45 +1346,6 @@ def CommonPath(PathList): return os.path.sep.join(P1[:Index]) return os.path.sep.join(P1) -# -# Convert string to C format array -# -def ConvertStringToByteArray(Value): - Value = Value.strip() - if not Value: - return None - if Value[0] == '{': - if not Value.endswith('}'): - return None - Value = Value.replace(' ', '').replace('{', '').replace('}', '') - ValFields = Value.split(',') - try: - for Index in range(len(ValFields)): - ValFields[Index] = str(int(ValFields[Index], 0)) - except ValueError: - return None - Value = '{' + ','.join(ValFields) + '}' - return Value - - Unicode = False - if Value.startswith('L"'): - if not Value.endswith('"'): - return None - Value = Value[1:] - Unicode = True - elif not Value.startswith('"') or not Value.endswith('"'): - return None - - Value = eval(Value) # translate escape character - NewValue = '{' - for Index in range(0, len(Value)): - if Unicode: - NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ',' - else: - NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ',' - Value = NewValue + '0}' - return Value - class PathClass(object): def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False, Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''): @@ -1757,23 +1413,17 @@ class PathClass(object): # @retval True The two PathClass are the same # def __eq__(self, Other): - if isinstance(Other, type(self)): - return self.Path == Other.Path - else: - return self.Path == str(Other) + return self.Path == str(Other) ## Override __cmp__ function # - # Customize the comparsion operation of two PathClass + # Customize the comparison operation of two PathClass # # @retval 0 The two PathClass are different # @retval -1 The first PathClass is less than the second PathClass # @retval 1 The first PathClass is Bigger than the second PathClass def __cmp__(self, Other): - if isinstance(Other, type(self)): - OtherKey = Other.Path - else: - OtherKey = str(Other) + OtherKey = str(Other) SelfKey = self.Path if SelfKey == OtherKey: @@ -1801,6 +1451,32 @@ class PathClass(object): return os.stat(self.Path)[8] def Validate(self, Type='', CaseSensitive=True): + def RealPath2(File, Dir='', OverrideDir=''): + NewFile = None + if OverrideDir: + NewFile = GlobalData.gAllFiles[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)] + if GlobalData.gAllFiles: + NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))] + if not NewFile: + NewFile = os.path.normpath(os.path.join(Dir, File)) + if not os.path.exists(NewFile): + return None, None + 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 + if GlobalData.gCaseInsensitive: CaseSensitive = False if Type and Type.lower() != self.Type: @@ -1836,7 +1512,7 @@ class PathClass(object): self.Path = os.path.join(RealRoot, RealFile) return ErrorCode, ErrorInfo -## Parse PE image to get the required PE informaion. +## Parse PE image to get the required PE information. # class PeImageClass(): ## Constructor @@ -1871,7 +1547,7 @@ class PeImageClass(): ByteArray = array.array('B') ByteArray.fromfile(PeObject, 4) # PE signature should be 'PE\0\0' - if ByteArray.tostring() != 'PE\0\0': + if ByteArray.tostring() != b'PE\0\0': self.ErrorInfo = self.FileName + ' has no valid PE signature PE00' return @@ -1963,7 +1639,7 @@ class SkuClass(): ExtraData = "SKU-ID [%s] value %s exceeds the max value of UINT64" % (SkuName, SkuId)) - self.AvailableSkuIds = sdict() + self.AvailableSkuIds = OrderedDict() self.SkuIdSet = [] self.SkuIdNumberSet = [] self.SkuData = SkuIds @@ -1973,7 +1649,7 @@ class SkuClass(): self.SkuIdSet = ['DEFAULT'] self.SkuIdNumberSet = ['0U'] elif SkuIdentifier == 'ALL': - self.SkuIdSet = SkuIds.keys() + self.SkuIdSet = list(SkuIds.keys()) self.SkuIdNumberSet = [num[0].strip() + 'U' for num in SkuIds.values()] else: r = SkuIdentifier.split('|') @@ -2080,12 +1756,6 @@ class SkuClass(): else: return 'DEFAULT' -# -# Pack a registry format GUID -# -def PackRegistryFormatGuid(Guid): - return PackGUID(Guid.split('-')) - ## Get the integer value from string like "14U" or integer like 2 # # @param Input The object that may be either a integer value or a string @@ -2093,7 +1763,7 @@ def PackRegistryFormatGuid(Guid): # @retval Value The integer value that the input represents # def GetIntegerValue(Input): - if isinstance(Input, int): + if not isinstance(Input, str): return Input String = Input if String.endswith("U"): @@ -2146,11 +1816,26 @@ def PackByteFormatGUID(Guid): Guid[10], ) -## +## DeepCopy dict/OrderedDict recusively # -# This acts like the main() function for the script, unless it is 'import'ed into another -# script. +# @param ori_dict a nested dict or ordereddict # -if __name__ == '__main__': - pass +# @retval new dict or orderdict +# +def CopyDict(ori_dict): + dict_type = ori_dict.__class__ + if dict_type not in (dict,OrderedDict): + return ori_dict + new_dict = dict_type() + for key in ori_dict: + if isinstance(ori_dict[key],(dict,OrderedDict)): + new_dict[key] = CopyDict(ori_dict[key]) + else: + new_dict[key] = ori_dict[key] + return new_dict +# +# Remove the c/c++ comments: // and /* */ +# +def RemoveCComments(ctext): + return re.sub('//.*?\n|/\*.*?\*/', '\n', ctext, flags=re.S)