1. Add API 'append' to class sdict
[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 from UserDict import IterableUserDict\r
26 from UserList import UserList\r
27 \r
28 from Common import EdkLogger as EdkLogger\r
29 from BuildToolError import *\r
30 \r
31 ## Regular expression used to find out place holders in string template\r
32 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE|re.UNICODE)\r
33 \r
34 ## Dictionary used to store file time stamp for quick re-access\r
35 gFileTimeStampCache = {}    # {file path : file time stamp}\r
36 \r
37 ## Dictionary used to store dependencies of files\r
38 gDependencyDatabase = {}    # arch : {file path : [dependent files list]}\r
39 \r
40 ## callback routine for processing variable option\r
41 #\r
42 # This function can be used to process variable number of option values. The\r
43 # typical usage of it is specify architecure list on command line.\r
44 # (e.g. <tool> -a IA32 X64 IPF)\r
45 #\r
46 # @param  Option        Standard callback function parameter\r
47 # @param  OptionString  Standard callback function parameter\r
48 # @param  Value         Standard callback function parameter\r
49 # @param  Parser        Standard callback function parameter\r
50 #\r
51 # @retval\r
52 #\r
53 def ProcessVariableArgument(Option, OptionString, Value, Parser):\r
54     assert Value is None\r
55     Value = []\r
56     RawArgs = Parser.rargs\r
57     while RawArgs:\r
58         Arg = RawArgs[0]\r
59         if (Arg[:2] == "--" and len(Arg) > 2) or \\r
60            (Arg[:1] == "-" and len(Arg) > 1 and Arg[1] != "-"):\r
61             break\r
62         Value.append(Arg)\r
63         del RawArgs[0]\r
64     setattr(Parser.values, Option.dest, Value)\r
65 \r
66 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style\r
67 #\r
68 #   @param      Guid    The GUID string\r
69 #\r
70 #   @retval     string  The GUID string in C structure style\r
71 #\r
72 def GuidStringToGuidStructureString(Guid):\r
73     GuidList = Guid.split('-')\r
74     Result = '{'\r
75     for Index in range(0,3,1):\r
76         Result = Result + '0x' + GuidList[Index] + ', '\r
77     Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]\r
78     for Index in range(0,12,2):\r
79         Result = Result + ', 0x' + GuidList[4][Index:Index+2]\r
80     Result += '}}'\r
81     return Result\r
82 \r
83 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r
84 #\r
85 #   @param      GuidValue   The GUID value in C structure format\r
86 #\r
87 #   @retval     string      The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format\r
88 #\r
89 def GuidStructureStringToGuidString(GuidValue):\r
90     guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")\r
91     guidValueList = guidValueString.split(",")\r
92     if len(guidValueList) != 11:\r
93         EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)\r
94     return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (\r
95             int(guidValueList[0], 16),\r
96             int(guidValueList[1], 16),\r
97             int(guidValueList[2], 16),\r
98             int(guidValueList[3], 16),\r
99             int(guidValueList[4], 16),\r
100             int(guidValueList[5], 16),\r
101             int(guidValueList[6], 16),\r
102             int(guidValueList[7], 16),\r
103             int(guidValueList[8], 16),\r
104             int(guidValueList[9], 16),\r
105             int(guidValueList[10], 16)\r
106             )\r
107 \r
108 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx\r
109 #\r
110 #   @param      GuidValue   The GUID value in C structure format\r
111 #\r
112 #   @retval     string      The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format\r
113 #\r
114 def GuidStructureStringToGuidValueName(GuidValue):\r
115     guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "")\r
116     guidValueList = guidValueString.split(",")\r
117     if len(guidValueList) != 11:\r
118         EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)\r
119     return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (\r
120             int(guidValueList[0], 16),\r
121             int(guidValueList[1], 16),\r
122             int(guidValueList[2], 16),\r
123             int(guidValueList[3], 16),\r
124             int(guidValueList[4], 16),\r
125             int(guidValueList[5], 16),\r
126             int(guidValueList[6], 16),\r
127             int(guidValueList[7], 16),\r
128             int(guidValueList[8], 16),\r
129             int(guidValueList[9], 16),\r
130             int(guidValueList[10], 16)\r
131             )\r
132 \r
133 ## Create directories\r
134 #\r
135 #   @param      Directory   The directory name\r
136 #\r
137 def CreateDirectory(Directory):\r
138     if Directory == None or Directory.strip() == "":\r
139         return True\r
140     try:\r
141         if not os.access(Directory, os.F_OK):\r
142             os.makedirs(Directory)\r
143     except:\r
144         return False\r
145     return True\r
146 \r
147 ## Check if given file is changed or not\r
148 #\r
149 #  This method is used to check if a file is changed or not between two build\r
150 #  actions. It makes use a cache to store files timestamp.\r
151 #\r
152 #   @param      File    The path of file\r
153 #\r
154 #   @retval     True    If the given file is changed, doesn't exist, or can't be\r
155 #                       found in timestamp cache\r
156 #   @retval     False   If the given file is changed\r
157 #\r
158 def IsChanged(File):\r
159     if not os.path.exists(File):\r
160         return True\r
161 \r
162     FileState = os.stat(File)\r
163     TimeStamp = FileState[-2]\r
164 \r
165     if File in gFileTimeStampCache and TimeStamp <= gFileTimeStampCache[File]:\r
166         FileChanged = False\r
167     else:\r
168         FileChanged = True\r
169         gFileTimeStampCache[File] = TimeStamp\r
170 \r
171     return FileChanged\r
172 \r
173 ## Store content in file\r
174 #\r
175 #  This method is used to save file only when its content is changed. This is\r
176 #  quite useful for "make" system to decide what will be re-built and what won't.\r
177 #\r
178 #   @param      File            The path of file\r
179 #   @param      Content         The new content of the file\r
180 #   @param      IsBinaryFile    The flag indicating if the file is binary file or not\r
181 #\r
182 #   @retval     True            If the file content is changed and the file is renewed\r
183 #   @retval     False           If the file content is the same\r
184 #\r
185 def SaveFileOnChange(File, Content, IsBinaryFile=True):\r
186     if IsBinaryFile:\r
187         BinaryFlag = 'b'\r
188     else:\r
189         BinaryFlag = ''\r
190     Fd = None\r
191     if os.path.exists(File):\r
192         try:\r
193             Fd = open(File, "r"+BinaryFlag)\r
194         except:\r
195             EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File)\r
196         FileSize = os.fstat(Fd.fileno()).st_size\r
197         if len(Content) == FileSize and Content == Fd.read():\r
198             Fd.close()\r
199             return False\r
200         Fd.close()\r
201         # os.remove(File) # seems creating new file is faster than overwriting old one\r
202     CreateDirectory(os.path.dirname(File))\r
203     try:\r
204         Fd = open(File, "w"+BinaryFlag)\r
205     except:\r
206         EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File)\r
207     Fd.write(Content)\r
208     Fd.close()\r
209     return True\r
210 \r
211 ## Make a Python object persistent on file system\r
212 #\r
213 #   @param      Data    The object to be stored in file\r
214 #   @param      File    The path of file to store the object\r
215 #\r
216 def DataDump(Data, File):\r
217     Fd = None\r
218     try:\r
219         Fd = open(File, 'wb')\r
220         cPickle.dump(Data, Fd, cPickle.HIGHEST_PROTOCOL)\r
221     except:\r
222         EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False)\r
223     finally:\r
224         if Fd != None:\r
225             Fd.close()\r
226 \r
227 ## Restore a Python object from a file\r
228 #\r
229 #   @param      File    The path of file stored the object\r
230 #\r
231 #   @retval     object  A python object\r
232 #   @retval     None    If failure in file operation\r
233 #\r
234 def DataRestore(File):\r
235     Data = None\r
236     Fd = None\r
237     try:\r
238         Fd = open(File, 'rb')\r
239         Data = cPickle.load(Fd)\r
240     except Exception, e:\r
241         EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e)))\r
242         Data = None\r
243     finally:\r
244         if Fd != None:\r
245             Fd.close()\r
246     return Data\r
247 \r
248 ## Check if gvien file exists or not\r
249\r
250 #   @param      File    File name or path to be checked\r
251 #   @param      Dir     The directory the file is relative to\r
252\r
253 #   @retval     True    if file exists\r
254 #   @retval     False   if file doesn't exists\r
255\r
256 def ValidFile(File, Dir='.'):\r
257     Wd = os.getcwd()\r
258     os.chdir(Dir)\r
259     if not os.path.exists(File):\r
260         os.chdir(Wd)\r
261         return False\r
262     os.chdir(Wd)\r
263     return True\r
264 \r
265 ## Get GUID value from given packages\r
266\r
267 #   @param      CName           The CName of the GUID\r
268 #   @param      PackageList     List of packages looking-up in\r
269\r
270 #   @retval     GuidValue   if the CName is found in any given package\r
271 #   @retval     None        if the CName is not found in all given packages\r
272\r
273 def GuidValue(CName, PackageList):\r
274     for P in PackageList:\r
275         if CName in P.Guids:\r
276             return P.Guids[CName]\r
277         if CName in P.Protocols:\r
278             return P.Protocols[CName]\r
279         if CName in P.Ppis:\r
280             return P.Ppis[CName]\r
281     return None\r
282 \r
283 ## A string template class\r
284 #\r
285 #  This class implements a template for string replacement. A string template\r
286 #  looks like following\r
287 #\r
288 #       ${BEGIN} other_string ${placeholder_name} other_string ${END}\r
289 #\r
290 #  The string between ${BEGIN} and ${END} will be repeated as many times as the\r
291 #  length of "placeholder_name", which is a list passed through a dict. The\r
292 #  "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can\r
293 #  be not used and, in this case, the "placeholder_name" must not a list and it\r
294 #  will just be replaced once.\r
295 #\r
296 class TemplateString(object):\r
297     ## Constructor\r
298     def __init__(self):\r
299         self.String = ''\r
300 \r
301     ## str() operator\r
302     #\r
303     #   @retval     string  The string replaced\r
304     #\r
305     def __str__(self):\r
306         return self.String\r
307 \r
308     ## Replace the string template with dictionary of placeholders\r
309     #\r
310     #   @param      AppendString    The string template to append\r
311     #   @param      Dictionary      The placeholder dictionaries\r
312     #\r
313     def Append(self, AppendString, Dictionary=None):\r
314         if Dictionary == None:\r
315             self.String += AppendString\r
316             return\r
317 \r
318         # replace repeat ones, enclosed by ${BEGIN} and $(END)\r
319         while True:\r
320             Start = AppendString.find('${BEGIN}')\r
321             if Start < 0:\r
322                 break\r
323             End   = AppendString.find('${END}')\r
324 \r
325             # exclude the ${BEGIN} and ${END}\r
326             SubString = AppendString[Start + 8 : End]\r
327 \r
328             RepeatTime = -1\r
329             SubDict = {}\r
330             PlaceholderList = gPlaceholderPattern.findall(SubString)\r
331             for Key in PlaceholderList:\r
332                 if Key not in Dictionary:\r
333                     continue\r
334 \r
335                 Value = Dictionary[Key]\r
336                 if type(Value) != type([]):\r
337                     continue\r
338 \r
339                 SubDict[Key] = ""\r
340                 if RepeatTime < 0:\r
341                     RepeatTime = len(Value)\r
342                 elif RepeatTime != len(Value):\r
343                     EdkLogger.error("TemplateString", PARAMETER_INVALID, Key + " has different repeat time from others!",\r
344                                     ExtraData=str(Dictionary))\r
345 \r
346             NewString = ''\r
347             for Index in range(0, RepeatTime):\r
348                 for Key in SubDict:\r
349                     SubDict[Key] = Dictionary[Key][Index]\r
350                 NewString += string.Template(SubString).safe_substitute(SubDict)\r
351             AppendString = AppendString[0:Start] + NewString + AppendString[End + 6:]\r
352 \r
353         # replace single ones\r
354         SubDict = {}\r
355         for Key in Dictionary:\r
356             Value = Dictionary[Key]\r
357             if type(Value) == type([]):\r
358                 continue\r
359             SubDict[Key] = Value\r
360         AppendString = string.Template(AppendString).safe_substitute(SubDict)\r
361 \r
362         self.String += AppendString\r
363 \r
364 ## Progress indicator class\r
365 #\r
366 #  This class makes use of thread to print progress on console.\r
367 #\r
368 class Progressor:\r
369     # for avoiding deadloop\r
370     _StopFlag = None\r
371     _ProgressThread = None\r
372     ## Constructor\r
373     #\r
374     #   @param      OpenMessage     The string printed before progress charaters\r
375     #   @param      CloseMessage    The string printed after progress charaters\r
376     #   @param      ProgressChar    The charater used to indicate the progress\r
377     #   @param      Interval        The interval in seconds between two progress charaters\r
378     #\r
379     def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1):\r
380         self.PromptMessage = OpenMessage\r
381         self.CodaMessage = CloseMessage\r
382         self.ProgressChar = ProgressChar\r
383         self.Interval = Interval\r
384         if Progressor._StopFlag == None:\r
385             Progressor._StopFlag = threading.Event()\r
386 \r
387     ## Start to print progress charater\r
388     #\r
389     #   @param      OpenMessage     The string printed before progress charaters\r
390     #\r
391     def Start(self, OpenMessage=None):\r
392         if OpenMessage != None:\r
393             self.PromptMessage = OpenMessage\r
394         Progressor._StopFlag.clear()\r
395         if Progressor._ProgressThread == None:\r
396             Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry)\r
397             Progressor._ProgressThread.setDaemon(False)\r
398             Progressor._ProgressThread.start()\r
399 \r
400     ## Stop printing progress charater\r
401     #\r
402     #   @param      CloseMessage    The string printed after progress charaters\r
403     #\r
404     def Stop(self, CloseMessage=None):\r
405         OriginalCodaMessage = self.CodaMessage\r
406         if CloseMessage != None:\r
407             self.CodaMessage = CloseMessage\r
408         self.Abort()\r
409         self.CodaMessage = OriginalCodaMessage\r
410 \r
411     ## Thread entry method\r
412     def _ProgressThreadEntry(self):\r
413         print self.PromptMessage,\r
414         sys.stdout.flush()\r
415         while not Progressor._StopFlag.isSet():\r
416             print self.ProgressChar,\r
417             sys.stdout.flush()\r
418             time.sleep(self.Interval)\r
419         print self.CodaMessage\r
420         sys.stdout.flush()\r
421 \r
422     ## Abort the progress display\r
423     @staticmethod\r
424     def Abort():\r
425         if Progressor._StopFlag != None:\r
426             Progressor._StopFlag.set()\r
427         if Progressor._ProgressThread != None:\r
428             Progressor._ProgressThread.join()\r
429             Progressor._ProgressThread = None\r
430 \r
431 ## A dict which can access its keys and/or values orderly\r
432 #\r
433 #  The class implements a new kind of dict which its keys or values can be\r
434 #  accessed in the order they are added into the dict. It guarantees the order\r
435 #  by making use of an internal list to keep a copy of keys.\r
436 #\r
437 class sdict(IterableUserDict):\r
438     ## Constructor\r
439     def __init__(self):\r
440         IterableUserDict.__init__(self)\r
441         self._key_list = []\r
442 \r
443     ## [] operator\r
444     def __setitem__(self, key, value):\r
445         if key not in self._key_list:\r
446             self._key_list.append(key)\r
447         IterableUserDict.__setitem__(self, key, value)\r
448 \r
449     ## del operator\r
450     def __delitem__(self, key):\r
451         self._key_list.remove(key)\r
452         IterableUserDict.__delitem__(self, key)\r
453 \r
454     ## used in "for k in dict" loop to ensure the correct order\r
455     def __iter__(self):\r
456         return self.iterkeys()\r
457 \r
458     ## len() support\r
459     def __len__(self):\r
460         return len(self._key_list)\r
461 \r
462     ## "in" test support\r
463     def __contains__(self, key):\r
464         return key in self._key_list\r
465     \r
466     ## indexof support\r
467     def index(self, key):\r
468         return self._key_list.index(key)\r
469     \r
470     ## insert support\r
471     def insert(self, key, newkey, newvalue, order):\r
472         index = self._key_list.index(key)\r
473         if order == 'BEFORE':\r
474             self._key_list.insert(index, newkey)\r
475             IterableUserDict.__setitem__(self, newkey, newvalue)\r
476         elif order == 'AFTER':\r
477             self._key_list.insert(index + 1, newkey)\r
478             IterableUserDict.__setitem__(self, newkey, newvalue)\r
479 \r
480     ## append support\r
481     def append(self, sdict):\r
482         for key in sdict:\r
483             if key not in self._key_list:\r
484                 self._key_list.append(key)\r
485             IterableUserDict.__setitem__(self, key, sdict[key])\r
486         \r
487     def has_key(self, key):\r
488         return key in self._key_list\r
489 \r
490     ## Empty the dict\r
491     def clear(self):\r
492         self._key_list = []\r
493         IterableUserDict.clear(self)\r
494 \r
495     ## Return a copy of keys\r
496     def keys(self):\r
497         keys = []\r
498         for key in self._key_list:\r
499             keys.append(key)\r
500         return keys\r
501 \r
502     ## Return a copy of values\r
503     def values(self):\r
504         values = []\r
505         for key in self._key_list:\r
506             values.append(self[key])\r
507         return values\r
508 \r
509     ## Return a copy of (key, value) list\r
510     def items(self):\r
511         items = []\r
512         for key in self._key_list:\r
513             items.append((key, self[key]))\r
514         return items\r
515 \r
516     ## Iteration support\r
517     def iteritems(self):\r
518         return iter(self.items())\r
519 \r
520     ## Keys interation support\r
521     def iterkeys(self):\r
522         return iter(self.keys())\r
523 \r
524     ## Values interation support\r
525     def itervalues(self):\r
526         return iter(self.values())\r
527 \r
528     ## Return value related to a key, and remove the (key, value) from the dict\r
529     def pop(self, key, *dv):\r
530         value = None\r
531         if key in self._key_list:\r
532             value = self[key]\r
533             self.__delitem__(key)\r
534         elif len(dv) != 0 :\r
535             value = kv[0]\r
536         return value\r
537 \r
538     ## Return (key, value) pair, and remove the (key, value) from the dict\r
539     def popitem(self):\r
540         key = self._key_list[-1]\r
541         value = self[key]\r
542         self.__delitem__(key)\r
543         return key, value\r
544 \r
545     def update(self, dict=None, **kwargs):\r
546         if dict != None:\r
547             for k, v in dict.items():\r
548                 self[k] = v\r
549         if len(kwargs):\r
550             for k, v in kwargs.items():\r
551                 self[k] = v\r
552 \r
553 ## Dictionary with restricted keys\r
554 #\r
555 class rdict(dict):\r
556     ## Constructor\r
557     def __init__(self, KeyList):\r
558         for Key in KeyList:\r
559             dict.__setitem__(self, Key, "")\r
560 \r
561     ## []= operator\r
562     def __setitem__(self, key, value):\r
563         if key not in self:\r
564             EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key, \r
565                             ExtraData=", ".join(dict.keys(self)))\r
566         dict.__setitem__(self, key, value)\r
567 \r
568     ## =[] operator\r
569     def __getitem__(self, key):\r
570         if key not in self:\r
571             return ""\r
572         return dict.__getitem__(self, key)\r
573 \r
574     ## del operator\r
575     def __delitem__(self, key):\r
576         EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del")\r
577 \r
578     ## Empty the dict\r
579     def clear(self):\r
580         for Key in self:\r
581             self.__setitem__(Key, "")\r
582 \r
583     ## Return value related to a key, and remove the (key, value) from the dict\r
584     def pop(self, key, *dv):\r
585         EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop")\r
586 \r
587     ## Return (key, value) pair, and remove the (key, value) from the dict\r
588     def popitem(self):\r
589         EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem")\r
590 \r
591 ## Dictionary using prioritized list as key\r
592 #\r
593 class tdict:\r
594     _ListType = type([])\r
595     _TupleType = type(())\r
596     _Wildcard = 'COMMON'\r
597     _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '', '*', 'PLATFORM']\r
598 \r
599     def __init__(self, _Single_=False, _Level_=2):\r
600         self._Level_ = _Level_\r
601         self.data = {}\r
602         self._Single_ = _Single_\r
603     \r
604     # =[] operator\r
605     def __getitem__(self, key):\r
606         KeyType = type(key)\r
607         RestKeys = None\r
608         if KeyType == self._ListType or KeyType == self._TupleType:\r
609             FirstKey = key[0]\r
610             if len(key) > 1:\r
611                 RestKeys = key[1:]\r
612             elif self._Level_ > 1:\r
613                 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]\r
614         else:\r
615             FirstKey = key\r
616             if self._Level_ > 1:\r
617                 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]\r
618 \r
619         if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList:\r
620             FirstKey = self._Wildcard\r
621 \r
622         if self._Single_:\r
623             return self._GetSingleValue(FirstKey, RestKeys)\r
624         else:\r
625             return self._GetAllValues(FirstKey, RestKeys)\r
626 \r
627     def _GetSingleValue(self, FirstKey, RestKeys):\r
628         Value = None\r
629         #print "%s-%s" % (FirstKey, self._Level_) ,\r
630         if self._Level_ > 1:\r
631             if FirstKey == self._Wildcard:\r
632                 if FirstKey in self.data:\r
633                     Value = self.data[FirstKey][RestKeys]\r
634                 if Value == None:\r
635                     for Key in self.data:\r
636                         Value = self.data[Key][RestKeys]\r
637                         if Value != None: break\r
638             else:\r
639                 if FirstKey in self.data:\r
640                     Value = self.data[FirstKey][RestKeys]\r
641                 if Value == None and self._Wildcard in self.data:\r
642                     #print "Value=None"\r
643                     Value = self.data[self._Wildcard][RestKeys]\r
644         else:\r
645             if FirstKey == self._Wildcard:\r
646                 if FirstKey in self.data:\r
647                     Value = self.data[FirstKey]\r
648                 if Value == None:\r
649                     for Key in self.data:\r
650                         Value = self.data[Key]\r
651                         if Value != None: break\r
652             else:\r
653                 if FirstKey in self.data:\r
654                     Value = self.data[FirstKey]\r
655                 elif self._Wildcard in self.data:\r
656                     Value = self.data[self._Wildcard]\r
657         return Value\r
658 \r
659     def _GetAllValues(self, FirstKey, RestKeys):\r
660         Value = []\r
661         if self._Level_ > 1:\r
662             if FirstKey == self._Wildcard:\r
663                 for Key in self.data:\r
664                     Value += self.data[Key][RestKeys]\r
665             else:\r
666                 if FirstKey in self.data:\r
667                     Value += self.data[FirstKey][RestKeys]\r
668                 if self._Wildcard in self.data:\r
669                     Value += self.data[self._Wildcard][RestKeys]\r
670         else:\r
671             if FirstKey == self._Wildcard:\r
672                 for Key in self.data:\r
673                     Value.append(self.data[Key])\r
674             else:\r
675                 if FirstKey in self.data:\r
676                     Value.append(self.data[FirstKey])\r
677                 if self._Wildcard in self.data:\r
678                     Value.append(self.data[self._Wildcard])\r
679         return Value\r
680 \r
681     ## []= operator\r
682     def __setitem__(self, key, value):\r
683         KeyType = type(key)\r
684         RestKeys = None\r
685         if KeyType == self._ListType or KeyType == self._TupleType:\r
686             FirstKey = key[0]\r
687             if len(key) > 1:\r
688                 RestKeys = key[1:]\r
689             else:\r
690                 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]\r
691         else:\r
692             FirstKey = key\r
693             if self._Level_ > 1:\r
694                 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]\r
695 \r
696         if FirstKey in self._ValidWildcardList:\r
697             FirstKey = self._Wildcard\r
698         \r
699         if FirstKey not in self.data and self._Level_ > 0:\r
700             self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1)\r
701 \r
702         if self._Level_ > 1:\r
703             self.data[FirstKey][RestKeys] = value\r
704         else:\r
705             self.data[FirstKey] = value\r
706 \r
707     def SetGreedyMode(self):\r
708         self._Single_ = False\r
709         if self._Level_ > 1:\r
710             for Key in self.data:\r
711                 self.data[Key].SetGreedyMode()\r
712 \r
713     def SetSingleMode(self):\r
714         self._Single_ = True\r
715         if self._Level_ > 1:\r
716             for Key in self.data:\r
717                 self.data[Key].SetSingleMode()\r
718 \r
719 ## Boolean chain list\r
720\r
721 class Blist(UserList):\r
722     def __init__(self, initlist=None):\r
723         UserList.__init__(self, initlist)\r
724     def __setitem__(self, i, item):\r
725         if item not in [True, False]:\r
726             if item == 0:\r
727                 item = False\r
728             else:\r
729                 item = True\r
730         self.data[i] = item\r
731     def _GetResult(self):\r
732         Value = True\r
733         for item in self.data:\r
734             Value &= item\r
735         return Value\r
736     Result = property(_GetResult)\r
737 \r
738 def ParseConsoleLog(Filename):\r
739     Opr = open(os.path.normpath(Filename), 'r')\r
740     Opw = open(os.path.normpath(Filename + '.New'), 'w+')\r
741     for Line in Opr.readlines():\r
742         if Line.find('.efi') > -1:\r
743             Opw.write('%s' % Line)\r
744     \r
745     Opr.close()\r
746     Opw.close()\r
747 \r
748 ##\r
749 #\r
750 # This acts like the main() function for the script, unless it is 'import'ed into another\r
751 # script.\r
752 #\r
753 if __name__ == '__main__':\r
754     ParseConsoleLog('C:\\1.log')\r
755     #print GuidStringToGuidStructureString('9EA5DF0F-A35C-48C1-BAC9-F63452B47C3E')\r
756 #    d = tdict(True, 3)\r
757 #    d['COMMON', 'PEIM', "A",] = 1\r
758 #    d['COMMON', 'DXE_CORE', 'B'] = 2\r
759 #    d['IA32', 'DXE_CORE', 'C'] = 3\r
760 #\r
761 #    print d['IA32', 'DXE_CORE', 'C']\r
762 #    \r
763 #    s = sdict()\r
764 #    s[1] = 1\r
765 #    s[3] = 3\r
766 #    s[4] = 4\r
767 #    s[6] = 6\r
768 #    print s.index(3)\r
769 #    s.insert(3, 2, 2, 'BEFORE')\r
770 #    print s.index(3)\r
771 #    print s.index(4)\r
772 #    s.insert(3, 5, 5, 'AFTER')\r
773 #    print s.keys()\r
774 #    print s.values()\r
775 #    for item in s:\r
776 #        print item, s[item]\r
777 \r