]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Common/Misc.py
BaseTools: Customize deepcopy function.
[mirror_edk2.git] / BaseTools / Source / Python / Common / Misc.py
index 5e7b163939e9262f8764dcde0bd8f3f86fae4b52..b063f064fb9b89db3d23dfd22f0bd57841b069e6 100644 (file)
@@ -14,6 +14,7 @@
 ##\r
 # Import Modules\r
 #\r
+from __future__ import absolute_import\r
 import Common.LongFilePathOs as os\r
 import sys\r
 import string\r
@@ -23,6 +24,7 @@ import re
 import pickle\r
 import array\r
 import shutil\r
+from random import sample\r
 from struct import pack\r
 from UserDict import IterableUserDict\r
 from UserList import UserList\r
@@ -39,6 +41,7 @@ import uuid
 from CommonDataClass.Exceptions import BadExpression\r
 from Common.caching import cached_property\r
 import subprocess\r
+from collections import OrderedDict\r
 ## Regular expression used to find out place holders in string template\r
 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)\r
 \r
@@ -49,6 +52,8 @@ valuePatternGcc = re.compile('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$')
 pcdPatternGcc = re.compile('^([\da-fA-Fx]+) +([\da-fA-Fx]+)')\r
 secReGeneral = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE)\r
 \r
+StructPattern = re.compile(r'[_a-zA-Z][0-9A-Za-z_]*$')\r
+\r
 ## Dictionary used to store file time stamp for quick re-access\r
 gFileTimeStampCache = {}    # {file path : file time stamp}\r
 \r
@@ -474,19 +479,9 @@ def SaveFileOnChange(File, Content, IsBinaryFile=True):
             EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName)\r
 \r
     try:\r
-        if GlobalData.gIsWindows:\r
-            try:\r
-                from .PyUtility import SaveFileToDisk\r
-                if not SaveFileToDisk(File, Content):\r
-                    EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File)\r
-            except:\r
-                Fd = open(File, "wb")\r
-                Fd.write(Content)\r
-                Fd.close()\r
-        else:\r
-            Fd = open(File, "wb")\r
-            Fd.write(Content)\r
-            Fd.close()\r
+        Fd = open(File, "wb")\r
+        Fd.write(Content)\r
+        Fd.close()\r
     except IOError as X:\r
         EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X)\r
 \r
@@ -784,7 +779,7 @@ class TemplateString(object):
 \r
     ## Constructor\r
     def __init__(self, Template=None):\r
-        self.String = ''\r
+        self.String = []\r
         self.IsBinary = False\r
         self._Template = Template\r
         self._TemplateSectionList = self._Parse(Template)\r
@@ -794,7 +789,7 @@ class TemplateString(object):
     #   @retval     string  The string replaced\r
     #\r
     def __str__(self):\r
-        return self.String\r
+        return "".join(self.String)\r
 \r
     ## Split the template string into fragments per the ${BEGIN} and ${END} flags\r
     #\r
@@ -842,9 +837,12 @@ class TemplateString(object):
     def Append(self, AppendString, Dictionary=None):\r
         if Dictionary:\r
             SectionList = self._Parse(AppendString)\r
-            self.String += "".join(S.Instantiate(Dictionary) for S in SectionList)\r
+            self.String.append( "".join(S.Instantiate(Dictionary) for S in SectionList))\r
         else:\r
-            self.String += AppendString\r
+            if isinstance(AppendString,list):\r
+                self.String.extend(AppendString)\r
+            else:\r
+                self.String.append(AppendString)\r
 \r
     ## Replace the string template with dictionary of placeholders\r
     #\r
@@ -1094,7 +1092,7 @@ class tdict:
     _ListType = type([])\r
     _TupleType = type(())\r
     _Wildcard = 'COMMON'\r
-    _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']\r
+    _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', TAB_STAR, 'PLATFORM']\r
 \r
     def __init__(self, _Single_=False, _Level_=2):\r
         self._Level_ = _Level_\r
@@ -1243,7 +1241,8 @@ def IsFieldValueAnArray (Value):
     return False\r
 \r
 def AnalyzePcdExpression(Setting):\r
-    Setting = Setting.strip()\r
+    RanStr = ''.join(sample(string.ascii_letters + string.digits, 8))\r
+    Setting = Setting.replace('\\\\', RanStr).strip()\r
     # There might be escaped quote in a string: \", \\\" , \', \\\'\r
     Data = Setting\r
     # There might be '|' in string and in ( ... | ... ), replace it with '-'\r
@@ -1276,7 +1275,9 @@ def AnalyzePcdExpression(Setting):
             break\r
         FieldList.append(Setting[StartPos:Pos].strip())\r
         StartPos = Pos + 1\r
-\r
+    for i, ch in enumerate(FieldList):\r
+        if RanStr in ch:\r
+            FieldList[i] = ch.replace(RanStr,'\\\\')\r
     return FieldList\r
 \r
 def ParseDevPathValue (Value):\r
@@ -1300,6 +1301,8 @@ def ParseDevPathValue (Value):
     return '{' + out + '}', Size\r
 \r
 def ParseFieldValue (Value):\r
+    if "{CODE(" in Value:\r
+        return Value, len(Value.split(","))\r
     if isinstance(Value, type(0)):\r
         return Value, (Value.bit_length() + 7) / 8\r
     if not isinstance(Value, type('')):\r
@@ -1468,7 +1471,7 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
         Size = ''\r
         if len(FieldList) > 1 and FieldList[1]:\r
             DataType = FieldList[1]\r
-            if FieldList[1] != TAB_VOID:\r
+            if FieldList[1] != TAB_VOID and StructPattern.match(FieldList[1]) is None:\r
                 IsValid = False\r
         if len(FieldList) > 2:\r
             Size = FieldList[2]\r
@@ -1745,10 +1748,7 @@ class PathClass(object):
     # @retval True  The two PathClass are the same\r
     #\r
     def __eq__(self, Other):\r
-        if isinstance(Other, type(self)):\r
-            return self.Path == Other.Path\r
-        else:\r
-            return self.Path == str(Other)\r
+        return self.Path == str(Other)\r
 \r
     ## Override __cmp__ function\r
     #\r
@@ -1758,10 +1758,7 @@ class PathClass(object):
     # @retval -1    The first PathClass is less than the second PathClass\r
     # @retval 1     The first PathClass is Bigger than the second PathClass\r
     def __cmp__(self, Other):\r
-        if isinstance(Other, type(self)):\r
-            OtherKey = Other.Path\r
-        else:\r
-            OtherKey = str(Other)\r
+        OtherKey = str(Other)\r
 \r
         SelfKey = self.Path\r
         if SelfKey == OtherKey:\r
@@ -2134,6 +2131,21 @@ def PackByteFormatGUID(Guid):
                 Guid[10],\r
                 )\r
 \r
+## DeepCopy dict/OrderedDict recusively\r
+#\r
+#   @param      ori_dict    a nested dict or ordereddict\r
+#\r
+#   @retval     new dict or orderdict\r
+#\r
+def CopyDict(ori_dict):\r
+    dict_type = ori_dict.__class__\r
+    new_dict = dict_type()\r
+    for key in ori_dict:\r
+        if isinstance(ori_dict[key],(dict,OrderedDict)):\r
+            new_dict[key] = CopyDict(ori_dict[key])\r
+        else:\r
+            new_dict[key] = ori_dict[key]\r
+    return new_dict\r
 ##\r
 #\r
 # This acts like the main() function for the script, unless it is 'import'ed into another\r