70fbce392a3256fcd85ed84b311e7e1628543393
[people/mcb30/basetools.git] / Source / Python / Common / Misc.py
1 ## @file\r
2 # Common routines used by all tools\r
3 #\r
4 # Copyright (c) 2007, Intel Corporation\r
5 # All rights reserved. This program and the accompanying materials\r
6 # are licensed and made available under the terms and conditions of the BSD License\r
7 # which accompanies this distribution.  The full text of the license may be found at\r
8 # http://opensource.org/licenses/bsd-license.php\r
9 #\r
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 #\r
13 \r
14 ##\r
15 # Import Modules\r
16 #\r
17 import os\r
18 import sys\r
19 import string\r
20 import thread\r
21 import threading\r
22 import time\r
23 import re\r
24 import cPickle\r
25 \r
26 from Common.BuildToolError import *\r
27 \r
28 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE|re.UNICODE)\r
29 gFileTimeStampCache = {}    # {file path : file time stamp}\r
30 gDependencyDatabase = {}    # file path : [dependent files list]\r
31 \r
32 ## callback routine for processing variable option\r
33 #\r
34 # This function can be used to process variable number of option values. The\r
35 # typical usage of it is specify architecure list on command line.\r
36 # (e.g. <tool> -a IA32 X64 IPF)\r
37 #\r
38 # @param  Option        Standard callback function parameter\r
39 # @param  OptionString  Standard callback function parameter\r
40 # @param  Value         Standard callback function parameter\r
41 # @param  Parser        Standard callback function parameter\r
42 #\r
43 # @retval\r
44 #\r
45 def ProcessVariableArgument(Option, OptionString, Value, Parser):\r
46     assert Value is None\r
47     Value = []\r
48     RawArgs = Parser.rargs\r
49     while RawArgs:\r
50         Arg = RawArgs[0]\r
51         if (Arg[:2] == "--" and len(Arg) > 2) or \\r
52            (Arg[:1] == "-" and len(Arg) > 1 and Arg[1] != "-"):\r
53             break\r
54         Value.append(Arg)\r
55         del RawArgs[0]\r
56     setattr(Parser.values, Option.dest, Value)\r
57 \r
58 def GuidStringToGuidStructureString(Guid):\r
59   GuidList = Guid.split('-')\r
60   Result = '{'\r
61   for Index in range(0,3,1):\r
62     Result = Result + '0x' + GuidList[Index] + ', '\r
63   Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]\r
64   for Index in range(0,12,2):\r
65     Result = Result + ', 0x' + GuidList[4][Index:Index+2]\r
66   Result += '}}'\r
67   return Result\r
68 \r
69 def GuidStructureStringToGuidString(GuidValue):\r
70     guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "")\r
71     guidValueList = guidValueString.split(",")\r
72     if len(guidValueList) != 11:\r
73         raise AutoGenError(msg="Invalid GUID value string %s" % GuidValue)\r
74     return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (\r
75             int(guidValueList[0], 16),\r
76             int(guidValueList[1], 16),\r
77             int(guidValueList[2], 16),\r
78             int(guidValueList[3], 16),\r
79             int(guidValueList[4], 16),\r
80             int(guidValueList[5], 16),\r
81             int(guidValueList[6], 16),\r
82             int(guidValueList[7], 16),\r
83             int(guidValueList[8], 16),\r
84             int(guidValueList[9], 16),\r
85             int(guidValueList[10], 16)\r
86             )\r
87 \r
88 def GuidStructureStringToGuidValueName(GuidValue):\r
89     guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "")\r
90     guidValueList = guidValueString.split(",")\r
91     if len(guidValueList) != 11:\r
92         raise AutoGenError(msg="Invalid GUID value string %s" % GuidValue)\r
93     return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (\r
94             int(guidValueList[0], 16),\r
95             int(guidValueList[1], 16),\r
96             int(guidValueList[2], 16),\r
97             int(guidValueList[3], 16),\r
98             int(guidValueList[4], 16),\r
99             int(guidValueList[5], 16),\r
100             int(guidValueList[6], 16),\r
101             int(guidValueList[7], 16),\r
102             int(guidValueList[8], 16),\r
103             int(guidValueList[9], 16),\r
104             int(guidValueList[10], 16)\r
105             )\r
106 \r
107 def CreateDirectory(Directory):\r
108     if not os.access(Directory, os.F_OK):\r
109         os.makedirs(Directory)\r
110 \r
111 def IsChanged(File):\r
112     FileState = os.stat(File)\r
113     TimeStamp = FileState[-2]\r
114 \r
115     if File in gFileTimeStampCache and TimeStamp <= gFileTimeStampCache[File]:\r
116         FileChanged = False\r
117     else:\r
118         FileChanged = True\r
119         gFileTimeStampCache[File] = TimeStamp\r
120 \r
121     return FileChanged\r
122 \r
123 def SaveFileOnChange(File, Content, IsBinaryFile=False):\r
124     if IsBinaryFile:\r
125         BinaryFlag = 'b'\r
126     else:\r
127         BinaryFlag = ''\r
128     Fd = None\r
129     if os.path.exists(File):\r
130         Fd = open(File, "r"+BinaryFlag)\r
131         if Content == Fd.read():\r
132             Fd.close()\r
133             return False\r
134         Fd.close()\r
135     CreateDirectory(os.path.dirname(File))\r
136     Fd = open(File, "w"+BinaryFlag)\r
137     Fd.write(Content)\r
138     Fd.close()\r
139     return True\r
140 \r
141 def Cache(Data, File):\r
142     Fd = None\r
143     try:\r
144         Fd = open(File, 'w')\r
145         cPickle.dump(Data, Fd)\r
146     except:\r
147         raise AutoGenError(FILE_OPEN_FAILURE, name=File)\r
148     finally:\r
149         if Fd != None:\r
150             Fd.close()\r
151 \r
152 def Restore(File):\r
153     try:\r
154         Fd = open(File, 'r')\r
155         return cPickle.load(Fd)\r
156     except Exception, e:\r
157         raise AutoGenError(FILE_OPEN_FAILURE, name=File)\r
158     finally:\r
159         if Fd != None:\r
160             Fd.close()\r
161 \r
162 class TemplateString(object):\r
163     def __init__(self):\r
164         self.String = ''\r
165 \r
166     def __str__(self):\r
167         return self.String\r
168 \r
169     def Append(self, AppendString, Dictionary=None):\r
170         if Dictionary == None:\r
171             self.String += AppendString\r
172             return\r
173 \r
174         # replace repeat ones, enclosed by ${BEGIN} and $(END)\r
175         while True:\r
176             Start = AppendString.find('${BEGIN}')\r
177             if Start < 0:\r
178                 break\r
179             End   = AppendString.find('${END}')\r
180 \r
181             # exclude the ${BEGIN} and ${END}\r
182             SubString = AppendString[Start + 8 : End]\r
183 \r
184             RepeatTime = -1\r
185             SubDict = {}\r
186             PlaceholderList = gPlaceholderPattern.findall(SubString)\r
187             for Key in PlaceholderList:\r
188                 if Key not in Dictionary:\r
189                     continue\r
190 \r
191                 Value = Dictionary[Key]\r
192                 if type(Value) != type([]):\r
193                     continue\r
194 \r
195                 SubDict[Key] = ""\r
196                 if RepeatTime < 0:\r
197                     RepeatTime = len(Value)\r
198                 elif RepeatTime != len(Value):\r
199                     raise AutoGenError(msg=Key + " has different repeat time from others!")\r
200 \r
201             NewString = ''\r
202             for Index in range(0, RepeatTime):\r
203                 for Key in SubDict:\r
204                     SubDict[Key] = Dictionary[Key][Index]\r
205                 NewString += string.Template(SubString).safe_substitute(SubDict)\r
206             AppendString = AppendString[0:Start] + NewString + AppendString[End + 6:]\r
207 \r
208         # replace single ones\r
209         SubDict = {}\r
210         for Key in Dictionary:\r
211             Value = Dictionary[Key]\r
212             if type(Value) == type([]):\r
213                 continue\r
214             SubDict[Key] = Value\r
215         AppendString = string.Template(AppendString).safe_substitute(SubDict)\r
216 \r
217         self.String += AppendString\r
218 \r
219 class Progressor:\r
220     def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1):\r
221         self.StopFlag = threading.Event()\r
222         self.ProgressThread = None\r
223         self.PromptMessage = OpenMessage\r
224         self.CodaMessage = CloseMessage\r
225         self.ProgressChar = ProgressChar\r
226         self.Interval = Interval\r
227 \r
228     def Start(self, OpenMessage=None):\r
229         if OpenMessage != None:\r
230             self.PromptMessage = OpenMessage\r
231         self.StopFlag.clear()\r
232         self.ProgressThread = threading.Thread(target=self._ProgressThreadEntry)\r
233         self.ProgressThread.setDaemon(True)\r
234         self.ProgressThread.start()\r
235 \r
236     def Stop(self, CloseMessage=None):\r
237         if CloseMessage != None:\r
238             self.CodaMessage = CloseMessage\r
239         self.StopFlag.set()\r
240         self.ProgressThread.join()\r
241         self.ProgressThread = None\r
242 \r
243     def _ProgressThreadEntry(self):\r
244         print self.PromptMessage,\r
245         while not self.StopFlag.isSet():\r
246             time.sleep(self.Interval)\r
247             print self.ProgressChar,\r
248         print self.CodaMessage\r
249 \r
250 class sdict(dict):\r
251     def __init__(self):\r
252         self._key_list = []\r
253 \r
254     def __setitem__(self, key, value):\r
255         if key not in self._key_list:\r
256             self._key_list.append(key)\r
257         dict.__setitem__(self, key, value)\r
258 \r
259     def __delitem__(self, key):\r
260         self._key_list.remove(key)\r
261         dict.__delitem__(self, key)\r
262     #\r
263     # used in "for k in dict" loop to ensure the correct order\r
264     #\r
265     def __iter__(self):\r
266         return self.iterkeys()\r
267 \r
268     def __len__(self):\r
269         return len(self._key_list)\r
270 \r
271     def __contains__(self, key):\r
272         return key in self._key_list\r
273 \r
274     def has_key(self, key):\r
275         return key in self._key_list\r
276 \r
277     def clear(self):\r
278         self._key_list = []\r
279         dict.clear(self)\r
280 \r
281     def keys(self):\r
282         keys = []\r
283         for key in self._key_list:\r
284             keys.append(key)\r
285         return keys\r
286 \r
287     def values(self):\r
288         values = []\r
289         for key in self._key_list:\r
290             values.append(self[key])\r
291         return values\r
292 \r
293     def items(self):\r
294         items = []\r
295         for key in self._key_list:\r
296             items.append((key, self[key]))\r
297         return items\r
298 \r
299     def iteritems(self):\r
300         return iter(self.items())\r
301 \r
302     def iterkeys(self):\r
303         return iter(self.keys())\r
304 \r
305     def itervalues(self):\r
306         return iter(self.values())\r
307 \r
308     def pop(self, key, *dv):\r
309         value = None\r
310         if key in self._key_list:\r
311             value = self[key]\r
312             dict.__delitem__(self, key)\r
313         elif len(dv) != 0 :\r
314             value = kv[0]\r
315         return value\r
316 \r
317     def popitem(self):\r
318         key = self._key_list[0]\r
319         value = self[key]\r
320         dict.__delitem__(self, key)\r
321         return key, value\r
322 \r
323 \r
324 if gFileTimeStampCache == {} and os.path.exists(".TsCache"):\r
325     gFileTimeStampCache = Restore(".TsCache")\r
326 \r
327 if gDependencyDatabase == {} and os.path.exists(".DepCache"):\r
328     gDependencyDatabase = Restore(".DepCache")\r