X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FMisc.py;h=5db9405ddc06264c53a2909b3f08e25efbc29ad7;hb=2e351cbe8e190271b3716284fc1076551d005472;hp=01171adb9b9e49754f0163873ae4d8feefe997c1;hpb=87d2afd07c822e6d5ab12bc8dc0f0bfa31bea679;p=mirror_edk2.git
diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py
index 01171adb9b..5db9405ddc 100644
--- a/BaseTools/Source/Python/Common/Misc.py
+++ b/BaseTools/Source/Python/Common/Misc.py
@@ -1,44 +1,41 @@
## @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 thread
import threading
import time
import re
-import cPickle
+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
-import subprocess
+from Common.caching import cached_property
+
## Regular expression used to find out place holders in string template
gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)
@@ -49,18 +46,24 @@ 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]}
+#
+# If a module is built more than once with different PCDs or library classes
+# a temporary INF file with same content is created, the temporary file is removed
+# when build exits.
+#
+_TempInfs = []
+
def GetVariableOffset(mapfilepath, efifilepath, varnames):
- """ Parse map file to get variable offset in current EFI file
+ """ Parse map file to get variable offset in current EFI file
@param mapfilepath Map file absolution path
@param efifilepath: EFI binary file full path
@param varnames iteratable container whose elements are variable names to be searched
-
+
@return List whos elements are tuple with variable name and raw offset
"""
lines = []
@@ -70,7 +73,7 @@ def GetVariableOffset(mapfilepath, efifilepath, varnames):
f.close()
except:
return None
-
+
if len(lines) == 0: return None
firstline = lines[0].strip()
if (firstline.startswith("Archive member included ") and
@@ -132,7 +135,7 @@ def _parseForGCC(lines, efifilepath, varnames):
if Str:
m = pcdPatternGcc.match(Str.strip())
if m is not None:
- varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0]))
+ varoffset.append((varname, int(m.groups(0)[0], 16), int(sections[-1][1], 16), sections[-1][0]))
if not varoffset:
return []
@@ -170,7 +173,7 @@ def _parseGeneral(lines, efifilepath, varnames):
continue
if line.startswith("entry point at"):
status = 3
- continue
+ continue
if status == 1 and len(line) != 0:
m = secReGeneral.match(line)
assert m is not None, "Fail to parse the section in map file , line is %s" % line
@@ -250,7 +253,7 @@ def ProcessDuplicatedInf(Path, BaseName, Workspace):
#
# A temporary INF is copied to database path which must have write permission
# The temporary will be removed at the end of build
- # In case of name conflict, the file name is
+ # In case of name conflict, the file name is
# FILE_GUIDBaseName (0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf)
#
TempFullPath = os.path.join(DbDir,
@@ -261,7 +264,7 @@ def ProcessDuplicatedInf(Path, BaseName, Workspace):
#
# To build same module more than once, the module path with FILE_GUID overridden has
# the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
- # in DSC which is used as relative path by C files and other files in INF.
+ # in DSC which is used as relative path by C files and other files in INF.
# A trick was used: all module paths are PathClass instances, after the initialization
# of PathClass, the PathClass.Path is overridden by the temporary INF path.
#
@@ -280,18 +283,18 @@ def ProcessDuplicatedInf(Path, BaseName, Workspace):
# If file exists, compare contents
#
if os.path.exists(TempFullPath):
- with open(str(Path), 'rb') as f1: Src = f1.read()
- with open(TempFullPath, 'rb') as f2: Dst = f2.read()
- if Src == Dst:
- return RtPath
- GlobalData.gTempInfs.append(TempFullPath)
+ with open(str(Path), 'rb') as f1, open(TempFullPath, 'rb') as f2:
+ if f1.read() == f2.read():
+ return RtPath
+ _TempInfs.append(TempFullPath)
shutil.copy2(str(Path), TempFullPath)
return RtPath
-## Remove temporary created INFs whose paths were saved in gTempInfs
+## Remove temporary created INFs whose paths were saved in _TempInfs
#
def ClearDuplicatedInf():
- for File in GlobalData.gTempInfs:
+ while _TempInfs:
+ File = _TempInfs.pop()
if os.path.exists(File):
os.remove(File)
@@ -353,6 +356,8 @@ def GuidStructureByteArrayToGuidString(GuidValue):
# @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
#
def GuidStructureStringToGuidString(GuidValue):
+ if not GlobalData.gGuidCFormatPattern.match(GuidValue):
+ return ''
guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
guidValueList = guidValueString.split(",")
if len(guidValueList) != 11:
@@ -445,15 +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 Content == open(File, "rb").read():
- return False
- except:
- EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File)
+ if IsBinaryFile:
+ try:
+ with open(File, "rb") as f:
+ if Content == f.read():
+ return False
+ 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)
DirName = os.path.dirname(File)
if not CreateDirectory(DirName):
@@ -464,62 +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:
- Fd = open(File, "wb")
+ if IsBinaryFile:
+ try:
+ with open(File, "wb") as Fd:
Fd.write(Content)
- Fd.close()
- else:
- Fd = open(File, "wb")
- Fd.write(Content)
- Fd.close()
- except IOError as X:
- EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X)
+ 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')
- cPickle.dump(Data, Fd, cPickle.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 = cPickle.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
@@ -599,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
@@ -636,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
@@ -775,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)
@@ -785,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
#
@@ -833,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
#
@@ -858,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
@@ -871,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:
@@ -884,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
@@ -919,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 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 = kv[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
#
@@ -1085,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_
@@ -1217,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 '-'
@@ -1267,33 +1004,38 @@ 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):
- if type(Value) == type(0):
- return Value, (Value.bit_length() + 7) / 8
- if type(Value) != type(''):
+ 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
+ if not isinstance(Value, type('')):
raise BadExpression('Type %s is %s' %(Value, type(Value)))
Value = Value.strip()
if Value.startswith(TAB_UINT8) and Value.endswith(')'):
@@ -1320,13 +1062,16 @@ def ParseFieldValue (Value):
Value = Value.split('(', 1)[1][:-1].strip()
if Value[0] == '{' and Value[-1] == '}':
TmpValue = GuidStructureStringToGuidString(Value)
- if len(TmpValue) == 0:
+ if not TmpValue:
raise BadExpression("Invalid GUID value string %s" % Value)
Value = TmpValue
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)
@@ -1407,15 +1152,18 @@ def ParseFieldValue (Value):
Value = Value.strip().strip('"')
return ParseDevPathValue(Value)
if Value.lower().startswith('0x'):
- Value = int(Value, 16)
+ try:
+ Value = int(Value, 16)
+ except:
+ 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':
@@ -1425,9 +1173,9 @@ def ParseFieldValue (Value):
## AnalyzeDscPcd
#
# Analyze DSC PCD value, since there is no data type info in DSC
-# This fuction is used to match functions (AnalyzePcdData) used for retrieving PCD value from database
+# This function is used to match functions (AnalyzePcdData) used for retrieving PCD value from database
# 1. Feature flag: TokenSpace.PcdCName|PcdValue
-# 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
+# 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
# 3. Dynamic default:
# TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
# TokenSpace.PcdCName|PcdValue
@@ -1435,7 +1183,7 @@ def ParseFieldValue (Value):
# TokenSpace.PcdCName|VpdOffset[|VpdValue]
# TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
# 5. Dynamic HII:
-# TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
+# TokenSpace.PcdCName|HiiString|VariableGuid|VariableOffset[|HiiValue]
# PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
# there might have "|" operator, also in string value.
#
@@ -1451,50 +1199,33 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
FieldList = AnalyzePcdExpression(Setting)
IsValid = True
- if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_FEATURE_FLAG):
+ if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
Value = FieldList[0]
Size = ''
- if len(FieldList) > 1:
- if FieldList[1].upper().startswith("0X") or FieldList[1].isdigit():
- Size = FieldList[1]
- else:
- DataType = FieldList[1]
-
- if len(FieldList) > 2:
- Size = FieldList[2]
- if DataType == "":
- IsValid = (len(FieldList) <= 1)
- else:
- IsValid = (len(FieldList) <= 3)
-# Value, Size = ParseFieldValue(Value)
- if Size:
- try:
- int(Size,16) if Size.upper().startswith("0X") else int(Size)
- except:
+ if len(FieldList) > 1 and FieldList[1]:
+ DataType = FieldList[1]
+ if FieldList[1] != TAB_VOID and StructPattern.match(FieldList[1]) is None:
IsValid = False
- Size = -1
- return [str(Value), '', str(Size)], IsValid, 0
- elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
- Value = FieldList[0]
- Size = Type = ''
- if len(FieldList) > 1:
- Type = FieldList[1]
- else:
- Type = DataType
if len(FieldList) > 2:
Size = FieldList[2]
- if DataType == "":
- IsValid = (len(FieldList) <= 1)
- else:
- IsValid = (len(FieldList) <= 3)
+ if IsValid:
+ if DataType == "":
+ IsValid = (len(FieldList) <= 1)
+ else:
+ IsValid = (len(FieldList) <= 3)
if Size:
try:
- int(Size,16) if Size.upper().startswith("0X") else int(Size)
+ int(Size, 16) if Size.upper().startswith("0X") else int(Size)
except:
IsValid = False
Size = -1
- return [Value, Type, str(Size)], IsValid, 0
+ return [str(Value), DataType, str(Size)], IsValid, 0
+ elif PcdType == MODEL_PCD_FEATURE_FLAG:
+ Value = FieldList[0]
+ Size = ''
+ IsValid = (len(FieldList) <= 1)
+ return [Value, DataType, str(Size)], IsValid, 0
elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):
VpdOffset = FieldList[0]
Value = Size = ''
@@ -1512,12 +1243,13 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
IsValid = (len(FieldList) <= 3)
if Size:
try:
- int(Size,16) if Size.upper().startswith("0X") else int(Size)
+ int(Size, 16) if Size.upper().startswith("0X") else int(Size)
except:
IsValid = False
Size = -1
return [VpdOffset, str(Size), Value], IsValid, 2
elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):
+ IsValid = (3 <= len(FieldList) <= 5)
HiiString = FieldList[0]
Guid = Offset = Value = Attribute = ''
if len(FieldList) > 1:
@@ -1528,7 +1260,6 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
Value = FieldList[3]
if len(FieldList) > 4:
Attribute = FieldList[4]
- IsValid = (3 <= len(FieldList) <= 5)
return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3
return [], False, 0
@@ -1538,29 +1269,29 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
# Used to avoid split issue while the value string contain "|" character
#
# @param[in] Setting: A String contain value/datum type/token number information;
-#
-# @retval ValueList: A List contain value, datum type and toke number.
+#
+# @retval ValueList: A List contain value, datum type and toke number.
#
def AnalyzePcdData(Setting):
ValueList = ['', '', '']
ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
PtrValue = ValueRe.findall(Setting)
-
+
ValueUpdateFlag = False
-
+
if len(PtrValue) >= 1:
Setting = re.sub(ValueRe, '', Setting)
ValueUpdateFlag = True
TokenList = Setting.split(TAB_VALUE_SPLIT)
ValueList[0:len(TokenList)] = TokenList
-
+
if ValueUpdateFlag:
ValueList[0] = PtrValue[0]
-
- return ValueList
-
+
+ return ValueList
+
## check format of PCD value against its the datum type
#
# For PCD value setting
@@ -1584,16 +1315,21 @@ def CheckPcdDatum(Type, Value):
Printset.add(TAB_PRINTCHAR_BS)
Printset.add(TAB_PRINTCHAR_NUL)
if not set(Value).issubset(Printset):
- PrintList = list(Printset)
- PrintList.sort()
+ PrintList = sorted(Printset)
return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type, PrintList)
elif Type == 'BOOLEAN':
if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
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.startswith('0') and not Value.lower().startswith('0x') and len(Value) > 1 and Value.lstrip('0'):
+ Value = Value.lstrip('0')
try:
- Value = long(Value, 0)
+ 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)
except:
return False, "Invalid value [%s] of type [%s];"\
" must be a hexadecimal, decimal or octal in C language format." % (Value, Type)
@@ -1602,82 +1338,14 @@ 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)
- for Index in xrange(min(len(P1), len(P2))):
+ for Index in range(min(len(P1), len(P2))):
if P1[Index] != P2[Index]:
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=''):
@@ -1728,8 +1396,6 @@ class PathClass(object):
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
@@ -1747,24 +1413,18 @@ class PathClass(object):
# @retval True The two PathClass are the same
#
def __eq__(self, Other):
- if type(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 type(Other) == type(self):
- OtherKey = Other.Path
- else:
- OtherKey = str(Other)
-
+ OtherKey = str(Other)
+
SelfKey = self.Path
if SelfKey == OtherKey:
return 0
@@ -1782,15 +1442,41 @@ class PathClass(object):
def __hash__(self):
return hash(self.Path)
- def _GetFileKey(self):
- if self._Key is None:
- self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
- return self._Key
+ @cached_property
+ def Key(self):
+ return self.Path.upper()
- def _GetTimeStamp(self):
+ @property
+ def TimeStamp(self):
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:
@@ -1826,10 +1512,7 @@ class PathClass(object):
self.Path = os.path.join(RealRoot, RealFile)
return ErrorCode, ErrorInfo
- Key = property(_GetFileKey)
- TimeStamp = property(_GetTimeStamp)
-
-## Parse PE image to get the required PE informaion.
+## Parse PE image to get the required PE information.
#
class PeImageClass():
## Constructor
@@ -1864,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
@@ -1902,7 +1585,7 @@ class PeImageClass():
def _ByteListToStr(self, ByteList):
String = ''
for index in range(len(ByteList)):
- if ByteList[index] == 0:
+ if ByteList[index] == 0:
break
String += chr(ByteList[index])
return String
@@ -1914,65 +1597,65 @@ class PeImageClass():
return Value
class DefaultStore():
- def __init__(self,DefaultStores ):
+ def __init__(self, DefaultStores ):
self.DefaultStores = DefaultStores
- def DefaultStoreID(self,DefaultStoreName):
- for key,value in self.DefaultStores.items():
+ def DefaultStoreID(self, DefaultStoreName):
+ for key, value in self.DefaultStores.items():
if value == DefaultStoreName:
return key
return None
def GetDefaultDefault(self):
if not self.DefaultStores or "0" in self.DefaultStores:
- return "0",TAB_DEFAULT_STORES_DEFAULT
+ return "0", TAB_DEFAULT_STORES_DEFAULT
else:
minvalue = min(int(value_str) for value_str in self.DefaultStores)
return (str(minvalue), self.DefaultStores[str(minvalue)])
- def GetMin(self,DefaultSIdList):
+ def GetMin(self, DefaultSIdList):
if not DefaultSIdList:
return TAB_DEFAULT_STORES_DEFAULT
storeidset = {storeid for storeid, storename in self.DefaultStores.values() if storename in DefaultSIdList}
if not storeidset:
return ""
minid = min(storeidset )
- for sid,name in self.DefaultStores.values():
+ for sid, name in self.DefaultStores.values():
if sid == minid:
return name
+
class SkuClass():
-
DEFAULT = 0
SINGLE = 1
MULTIPLE =2
-
+
def __init__(self,SkuIdentifier='', SkuIds=None):
if SkuIds is None:
SkuIds = {}
for SkuName in SkuIds:
SkuId = SkuIds[SkuName][0]
- skuid_num = int(SkuId,16) if SkuId.upper().startswith("0X") else int(SkuId)
+ skuid_num = int(SkuId, 16) if SkuId.upper().startswith("0X") else int(SkuId)
if skuid_num > 0xFFFFFFFFFFFFFFFF:
EdkLogger.error("build", PARAMETER_INVALID,
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
- self.__SkuInherit = {}
- self.__SkuIdentifier = SkuIdentifier
+ self._SkuInherit = {}
+ self._SkuIdentifier = SkuIdentifier
if SkuIdentifier == '' or SkuIdentifier is None:
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('|')
+ r = SkuIdentifier.split('|')
self.SkuIdSet=[(r[k].strip()).upper() for k in range(len(r))]
k = None
- try:
+ try:
self.SkuIdNumberSet = [SkuIds[k][0].strip() + 'U' for k in self.SkuIdSet]
except Exception:
EdkLogger.error("build", PARAMETER_INVALID,
@@ -1985,7 +1668,7 @@ class SkuClass():
EdkLogger.error("build", PARAMETER_INVALID,
ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
% (each, " | ".join(SkuIds.keys())))
- if self.SkuUsageType != self.SINGLE:
+ if self.SkuUsageType != SkuClass.SINGLE:
self.AvailableSkuIds.update({'DEFAULT':0, 'COMMON':0})
if self.SkuIdSet:
GlobalData.gSkuids = (self.SkuIdSet)
@@ -1999,18 +1682,18 @@ class SkuClass():
GlobalData.gSkuids.sort()
def GetNextSkuId(self, skuname):
- if not self.__SkuInherit:
- self.__SkuInherit = {}
+ if not self._SkuInherit:
+ self._SkuInherit = {}
for item in self.SkuData.values():
- self.__SkuInherit[item[1]]=item[2] if item[2] else "DEFAULT"
- return self.__SkuInherit.get(skuname,"DEFAULT")
+ self._SkuInherit[item[1]]=item[2] if item[2] else "DEFAULT"
+ return self._SkuInherit.get(skuname, "DEFAULT")
- def GetSkuChain(self,sku):
+ def GetSkuChain(self, sku):
if sku == "DEFAULT":
return ["DEFAULT"]
skulist = [sku]
nextsku = sku
- while 1:
+ while True:
nextsku = self.GetNextSkuId(nextsku)
skulist.append(nextsku)
if nextsku == "DEFAULT":
@@ -2021,7 +1704,7 @@ class SkuClass():
skuorderset = []
for skuname in self.SkuIdSet:
skuorderset.append(self.GetSkuChain(skuname))
-
+
skuorder = []
for index in range(max(len(item) for item in skuorderset)):
for subset in skuorderset:
@@ -2033,61 +1716,45 @@ class SkuClass():
return skuorder
- def __SkuUsageType(self):
-
- if self.__SkuIdentifier.upper() == "ALL":
+ @property
+ def SkuUsageType(self):
+ if self._SkuIdentifier.upper() == "ALL":
return SkuClass.MULTIPLE
if len(self.SkuIdSet) == 1:
if self.SkuIdSet[0] == 'DEFAULT':
return SkuClass.DEFAULT
- else:
- return SkuClass.SINGLE
- elif len(self.SkuIdSet) == 2:
- if 'DEFAULT' in self.SkuIdSet:
- return SkuClass.SINGLE
- else:
- return SkuClass.MULTIPLE
- else:
- return SkuClass.MULTIPLE
- def DumpSkuIdArrary(self):
+ return SkuClass.SINGLE
+ if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet:
+ return SkuClass.SINGLE
+ return SkuClass.MULTIPLE
- ArrayStrList = []
+ def DumpSkuIdArrary(self):
if self.SkuUsageType == SkuClass.SINGLE:
- ArrayStr = "{0x0}"
- else:
- for skuname in self.AvailableSkuIds:
- if skuname == "COMMON":
- continue
- while skuname != "DEFAULT":
- ArrayStrList.append(hex(int(self.AvailableSkuIds[skuname])))
- skuname = self.GetNextSkuId(skuname)
- ArrayStrList.append("0x0")
- ArrayStr = "{" + ",".join(ArrayStrList) + "}"
- return ArrayStr
- def __GetAvailableSkuIds(self):
+ return "{0x0}"
+ ArrayStrList = []
+ for skuname in self.AvailableSkuIds:
+ if skuname == "COMMON":
+ continue
+ while skuname != "DEFAULT":
+ ArrayStrList.append(hex(int(self.AvailableSkuIds[skuname])))
+ skuname = self.GetNextSkuId(skuname)
+ ArrayStrList.append("0x0")
+ return "{{{myList}}}".format(myList=",".join(ArrayStrList))
+
+ @property
+ def AvailableSkuIdSet(self):
return self.AvailableSkuIds
-
- def __GetSystemSkuID(self):
- if self.__SkuUsageType() == SkuClass.SINGLE:
+
+ @property
+ def SystemSkuId(self):
+ if self.SkuUsageType == SkuClass.SINGLE:
if len(self.SkuIdSet) == 1:
return self.SkuIdSet[0]
else:
return self.SkuIdSet[0] if self.SkuIdSet[0] != 'DEFAULT' else self.SkuIdSet[1]
else:
return 'DEFAULT'
- def __GetAvailableSkuIdNumber(self):
- return self.SkuIdNumberSet
- SystemSkuId = property(__GetSystemSkuID)
- AvailableSkuIdSet = property(__GetAvailableSkuIds)
- SkuUsageType = property(__SkuUsageType)
- AvailableSkuIdNumSet = property(__GetAvailableSkuIdNumber)
-
-#
-# Pack a registry format GUID
-#
-def PackRegistryFormatGuid(Guid):
- return PackGUID(Guid.split('-'))
## Get the integer value from string like "14U" or integer like 2
#
@@ -2096,7 +1763,7 @@ def PackRegistryFormatGuid(Guid):
# @retval Value The integer value that the input represents
#
def GetIntegerValue(Input):
- if type(Input) in (int, long):
+ if not isinstance(Input, str):
return Input
String = Input
if String.endswith("U"):
@@ -2149,11 +1816,26 @@ def PackByteFormatGUID(Guid):
Guid[10],
)
-##
+## DeepCopy dict/OrderedDict recusively
+#
+# @param ori_dict a nested dict or ordereddict
#
-# This acts like the main() function for the script, unless it is 'import'ed into another
-# script.
+# @retval new dict or orderdict
#
-if __name__ == '__main__':
- pass
+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)