]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/Misc.py
2 # Common routines used by all tools
4 # Copyright (c) 2007, Intel Corporation
5 # All rights reserved. This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 from UserDict
import IterableUserDict
26 from UserList
import UserList
28 from Common
import EdkLogger
as EdkLogger
29 from Common
import GlobalData
as GlobalData
31 from BuildToolError
import *
33 ## Regular expression used to find out place holders in string template
34 gPlaceholderPattern
= re
.compile("\$\{([^$()\s]+)\}", re
.MULTILINE|re
.UNICODE
)
36 ## Dictionary used to store file time stamp for quick re-access
37 gFileTimeStampCache
= {} # {file path : file time stamp}
39 ## Dictionary used to store dependencies of files
40 gDependencyDatabase
= {} # arch : {file path : [dependent files list]}
42 ## callback routine for processing variable option
44 # This function can be used to process variable number of option values. The
45 # typical usage of it is specify architecure list on command line.
46 # (e.g. <tool> -a IA32 X64 IPF)
48 # @param Option Standard callback function parameter
49 # @param OptionString Standard callback function parameter
50 # @param Value Standard callback function parameter
51 # @param Parser Standard callback function parameter
55 def ProcessVariableArgument(Option
, OptionString
, Value
, Parser
):
58 RawArgs
= Parser
.rargs
61 if (Arg
[:2] == "--" and len(Arg
) > 2) or \
62 (Arg
[:1] == "-" and len(Arg
) > 1 and Arg
[1] != "-"):
66 setattr(Parser
.values
, Option
.dest
, Value
)
68 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
70 # @param Guid The GUID string
72 # @retval string The GUID string in C structure style
74 def GuidStringToGuidStructureString(Guid
):
75 GuidList
= Guid
.split('-')
77 for Index
in range(0,3,1):
78 Result
= Result
+ '0x' + GuidList
[Index
] + ', '
79 Result
= Result
+ '{0x' + GuidList
[3][0:2] + ', 0x' + GuidList
[3][2:4]
80 for Index
in range(0,12,2):
81 Result
= Result
+ ', 0x' + GuidList
[4][Index
:Index
+2]
85 ## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
87 # @param GuidValue The GUID value in byte array
89 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
91 def GuidStructureByteArrayToGuidString(GuidValue
):
92 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
93 guidValueList
= guidValueString
.split(",")
94 if len(guidValueList
) != 16:
96 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
98 return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
99 int(guidValueList
[3], 16),
100 int(guidValueList
[2], 16),
101 int(guidValueList
[1], 16),
102 int(guidValueList
[0], 16),
103 int(guidValueList
[5], 16),
104 int(guidValueList
[4], 16),
105 int(guidValueList
[7], 16),
106 int(guidValueList
[6], 16),
107 int(guidValueList
[8], 16),
108 int(guidValueList
[9], 16),
109 int(guidValueList
[10], 16),
110 int(guidValueList
[11], 16),
111 int(guidValueList
[12], 16),
112 int(guidValueList
[13], 16),
113 int(guidValueList
[14], 16),
114 int(guidValueList
[15], 16)
119 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
121 # @param GuidValue The GUID value in C structure format
123 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
125 def GuidStructureStringToGuidString(GuidValue
):
126 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
127 guidValueList
= guidValueString
.split(",")
128 if len(guidValueList
) != 11:
130 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
132 return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
133 int(guidValueList
[0], 16),
134 int(guidValueList
[1], 16),
135 int(guidValueList
[2], 16),
136 int(guidValueList
[3], 16),
137 int(guidValueList
[4], 16),
138 int(guidValueList
[5], 16),
139 int(guidValueList
[6], 16),
140 int(guidValueList
[7], 16),
141 int(guidValueList
[8], 16),
142 int(guidValueList
[9], 16),
143 int(guidValueList
[10], 16)
148 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
150 # @param GuidValue The GUID value in C structure format
152 # @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
154 def GuidStructureStringToGuidValueName(GuidValue
):
155 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "")
156 guidValueList
= guidValueString
.split(",")
157 if len(guidValueList
) != 11:
158 EdkLogger
.error(None, None, "Invalid GUID value string %s" % GuidValue
)
159 return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (
160 int(guidValueList
[0], 16),
161 int(guidValueList
[1], 16),
162 int(guidValueList
[2], 16),
163 int(guidValueList
[3], 16),
164 int(guidValueList
[4], 16),
165 int(guidValueList
[5], 16),
166 int(guidValueList
[6], 16),
167 int(guidValueList
[7], 16),
168 int(guidValueList
[8], 16),
169 int(guidValueList
[9], 16),
170 int(guidValueList
[10], 16)
173 ## Create directories
175 # @param Directory The directory name
177 def CreateDirectory(Directory
):
178 if Directory
== None or Directory
.strip() == "":
181 if not os
.access(Directory
, os
.F_OK
):
182 os
.makedirs(Directory
)
187 ## Remove directories, including files and sub-directories in it
189 # @param Directory The directory name
191 def RemoveDirectory(Directory
, Recursively
=False):
192 if Directory
== None or Directory
.strip() == "" or not os
.path
.exists(Directory
):
195 CurrentDirectory
= os
.getcwd()
197 for File
in os
.listdir("."):
198 if os
.path
.isdir(File
):
199 RemoveDirectory(File
, Recursively
)
202 os
.chdir(CurrentDirectory
)
205 ## Check if given file is changed or not
207 # This method is used to check if a file is changed or not between two build
208 # actions. It makes use a cache to store files timestamp.
210 # @param File The path of file
212 # @retval True If the given file is changed, doesn't exist, or can't be
213 # found in timestamp cache
214 # @retval False If the given file is changed
217 if not os
.path
.exists(File
):
220 FileState
= os
.stat(File
)
221 TimeStamp
= FileState
[-2]
223 if File
in gFileTimeStampCache
and TimeStamp
== gFileTimeStampCache
[File
]:
227 gFileTimeStampCache
[File
] = TimeStamp
231 ## Store content in file
233 # This method is used to save file only when its content is changed. This is
234 # quite useful for "make" system to decide what will be re-built and what won't.
236 # @param File The path of file
237 # @param Content The new content of the file
238 # @param IsBinaryFile The flag indicating if the file is binary file or not
240 # @retval True If the file content is changed and the file is renewed
241 # @retval False If the file content is the same
243 def SaveFileOnChange(File
, Content
, IsBinaryFile
=True):
245 Content
= Content
.replace("\n", os
.linesep
)
247 if os
.path
.exists(File
):
249 if Content
== open(File
, "rb").read():
252 EdkLogger
.error(None, FILE_OPEN_FAILURE
, ExtraData
=File
)
254 CreateDirectory(os
.path
.dirname(File
))
256 if GlobalData
.gIsWindows
:
258 from PyUtility
import SaveFileToDisk
259 if not SaveFileToDisk(File
, Content
):
260 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
=File
)
262 Fd
= open(File
, "wb")
266 Fd
= open(File
, "wb")
270 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
=File
)
274 ## Make a Python object persistent on file system
276 # @param Data The object to be stored in file
277 # @param File The path of file to store the object
279 def DataDump(Data
, File
):
282 Fd
= open(File
, 'wb')
283 cPickle
.dump(Data
, Fd
, cPickle
.HIGHEST_PROTOCOL
)
285 EdkLogger
.error("", FILE_OPEN_FAILURE
, ExtraData
=File
, RaiseError
=False)
290 ## Restore a Python object from a file
292 # @param File The path of file stored the object
294 # @retval object A python object
295 # @retval None If failure in file operation
297 def DataRestore(File
):
301 Fd
= open(File
, 'rb')
302 Data
= cPickle
.load(Fd
)
304 EdkLogger
.verbose("Failed to load [%s]\n\t%s" % (File
, str(e
)))
311 ## Retrieve and cache the real path name in file system
313 # @param Root The root directory of path relative to
315 # @retval str The path string if the path exists
316 # @retval None If path doesn't exist
321 def __init__(self
, Root
):
323 for F
in os
.listdir(Root
):
324 self
._CACHE
_[F
.upper()] = F
327 def __getitem__(self
, Path
):
328 Path
= Path
[len(os
.path
.commonprefix([Path
, self
._Root
])):]
331 if Path
and Path
[0] == os
.path
.sep
:
334 if Path
in self
._CACHE
_:
335 return os
.path
.join(self
._Root
, self
._CACHE
_[Path
])
339 SepIndex
= Path
.find(os
.path
.sep
)
341 Parent
= Path
[:SepIndex
]
342 if Parent
not in self
._CACHE
_:
344 LastSepIndex
= SepIndex
345 SepIndex
= Path
.find(os
.path
.sep
, LastSepIndex
+ 1)
347 if LastSepIndex
== -1:
352 SepIndex
= LastSepIndex
354 ParentKey
= Path
[:SepIndex
]
355 if ParentKey
not in self
._CACHE
_:
359 ParentDir
= self
._CACHE
_[ParentKey
]
360 for F
in os
.listdir(ParentDir
):
361 Dir
= os
.path
.join(ParentDir
, F
)
362 self
._CACHE
_[Dir
.upper()] = Dir
364 SepIndex
= Path
.find(os
.path
.sep
, SepIndex
+ 1)
367 if Path
not in self
._CACHE
_:
369 return os
.path
.join(self
._Root
, self
._CACHE
_[Path
])
371 ## Get all files of a directory
373 # @param Root: Root dir
374 # @param SkipList : The files need be skipped
376 # @retval A list of all files
378 def GetFiles(Root
, SkipList
=None, FullPath
= True):
381 for Root
, Dirs
, Files
in os
.walk(Root
):
383 for Item
in SkipList
:
388 File
= os
.path
.normpath(os
.path
.join(Root
, File
))
390 File
= File
[len(OriPath
) + 1:]
391 FileList
.append(File
)
395 ## Check if gvien file exists or not
397 # @param File File name or path to be checked
398 # @param Dir The directory the file is relative to
400 # @retval True if file exists
401 # @retval False if file doesn't exists
403 def ValidFile(File
, Ext
=None):
405 Dummy
, FileExt
= os
.path
.splitext(File
)
406 if FileExt
.lower() != Ext
.lower():
408 if not os
.path
.exists(File
):
412 def RealPath(File
, Dir
='', OverrideDir
=''):
413 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
414 NewFile
= GlobalData
.gAllFiles
[NewFile
]
415 if not NewFile
and OverrideDir
:
416 NewFile
= os
.path
.normpath(os
.path
.join(OverrideDir
, File
))
417 NewFile
= GlobalData
.gAllFiles
[NewFile
]
420 def RealPath2(File
, Dir
='', OverrideDir
=''):
421 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
424 if Dir
[-1] == os
.path
.sep
:
425 return NewFile
[len(Dir
):], NewFile
[0:len(Dir
)]
427 return NewFile
[len(Dir
)+1:], NewFile
[0:len(Dir
)]
432 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
434 return NewFile
[len(OverrideDir
)+1:], NewFile
[0:len(OverrideDir
)]
437 ## Check if gvien file exists or not
440 def ValidFile2(AllFiles
, File
, Ext
=None, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
443 Dummy
, FileExt
= os
.path
.splitext(File
)
444 if FileExt
.lower() != Ext
.lower():
447 # Replace the R8 macros
448 if OverrideDir
!= '' and OverrideDir
!= None:
449 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
450 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
451 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
452 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
454 # Replace the default dir to current dir
457 Dir
= Dir
[len(Workspace
)+1:]
459 # First check if File has R8 definition itself
460 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
461 NewFile
= File
.replace('$(EFI_SOURCE)', EfiSource
)
462 NewFile
= NewFile
.replace('$(EDK_SOURCE)', EdkSource
)
463 NewFile
= AllFiles
[os
.path
.normpath(NewFile
)]
467 # Second check the path with override value
468 if OverrideDir
!= '' and OverrideDir
!= None:
469 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
473 # Last check the path with normal definitions
474 File
= os
.path
.join(Dir
, File
)
475 NewFile
= AllFiles
[os
.path
.normpath(File
)]
481 ## Check if gvien file exists or not
484 def ValidFile3(AllFiles
, File
, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
485 # Replace the R8 macros
486 if OverrideDir
!= '' and OverrideDir
!= None:
487 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
488 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
489 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
490 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
492 # Replace the default dir to current dir
493 # Dir is current module dir related to workspace
496 Dir
= Dir
[len(Workspace
)+1:]
499 RelaPath
= AllFiles
[os
.path
.normpath(Dir
)]
500 NewRelaPath
= RelaPath
503 # First check if File has R8 definition itself
504 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
505 File
= File
.replace('$(EFI_SOURCE)', EfiSource
)
506 File
= File
.replace('$(EDK_SOURCE)', EdkSource
)
507 NewFile
= AllFiles
[os
.path
.normpath(File
)]
509 NewRelaPath
= os
.path
.dirname(NewFile
)
510 File
= os
.path
.basename(NewFile
)
511 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
514 # Second check the path with override value
515 if OverrideDir
!= '' and OverrideDir
!= None:
516 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
518 #NewRelaPath = os.path.dirname(NewFile)
519 NewRelaPath
= NewFile
[:len(NewFile
) - len(File
.replace("..\\", '').replace("../", '')) - 1]
522 # Last check the path with normal definitions
523 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
530 return NewRelaPath
, RelaPath
, File
533 def GetRelPath(Path1
, Path2
):
534 FileName
= os
.path
.basename(Path2
)
535 L1
= os
.path
.normpath(Path1
).split(os
.path
.normpath('/'))
536 L2
= os
.path
.normpath(Path2
).split(os
.path
.normpath('/'))
537 for Index
in range(0, len(L1
)):
538 if L1
[Index
] != L2
[Index
]:
539 FileName
= '../' * (len(L1
) - Index
)
540 for Index2
in range(Index
, len(L2
)):
541 FileName
= os
.path
.join(FileName
, L2
[Index2
])
543 return os
.path
.normpath(FileName
)
546 ## Get GUID value from given packages
548 # @param CName The CName of the GUID
549 # @param PackageList List of packages looking-up in
551 # @retval GuidValue if the CName is found in any given package
552 # @retval None if the CName is not found in all given packages
554 def GuidValue(CName
, PackageList
):
555 for P
in PackageList
:
557 return P
.Guids
[CName
]
560 ## Get Protocol value from given packages
562 # @param CName The CName of the GUID
563 # @param PackageList List of packages looking-up in
565 # @retval GuidValue if the CName is found in any given package
566 # @retval None if the CName is not found in all given packages
568 def ProtocolValue(CName
, PackageList
):
569 for P
in PackageList
:
570 if CName
in P
.Protocols
:
571 return P
.Protocols
[CName
]
574 ## Get PPI value from given packages
576 # @param CName The CName of the GUID
577 # @param PackageList List of packages looking-up in
579 # @retval GuidValue if the CName is found in any given package
580 # @retval None if the CName is not found in all given packages
582 def PpiValue(CName
, PackageList
):
583 for P
in PackageList
:
588 ## A string template class
590 # This class implements a template for string replacement. A string template
591 # looks like following
593 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
595 # The string between ${BEGIN} and ${END} will be repeated as many times as the
596 # length of "placeholder_name", which is a list passed through a dict. The
597 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
598 # be not used and, in this case, the "placeholder_name" must not a list and it
599 # will just be replaced once.
601 class TemplateString(object):
602 _REPEAT_START_FLAG
= "BEGIN"
603 _REPEAT_END_FLAG
= "END"
605 class Section(object):
606 _LIST_TYPES
= [type([]), type(set()), type((0,))]
608 def __init__(self
, TemplateSection
, PlaceHolderList
):
609 self
._Template
= TemplateSection
610 self
._PlaceHolderList
= []
612 # Split the section into sub-sections according to the position of placeholders
614 self
._SubSectionList
= []
617 # The placeholders passed in must be in the format of
619 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
621 for PlaceHolder
,Start
,End
in PlaceHolderList
:
622 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:Start
])
623 self
._SubSectionList
.append(TemplateSection
[Start
:End
])
624 self
._PlaceHolderList
.append(PlaceHolder
)
625 SubSectionStart
= End
626 if SubSectionStart
< len(TemplateSection
):
627 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:])
629 self
._SubSectionList
= [TemplateSection
]
632 return self
._Template
+ " : " + str(self
._PlaceHolderList
)
634 def Instantiate(self
, PlaceHolderValues
):
636 RepeatPlaceHolders
= {}
637 NonRepeatPlaceHolders
= {}
639 for PlaceHolder
in self
._PlaceHolderList
:
640 if PlaceHolder
not in PlaceHolderValues
:
642 Value
= PlaceHolderValues
[PlaceHolder
]
643 if type(Value
) in self
._LIST
_TYPES
:
645 RepeatTime
= len(Value
)
646 elif RepeatTime
!= len(Value
):
650 "${%s} has different repeat time from others!" % PlaceHolder
,
651 ExtraData
=str(self
._Template
)
653 RepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
655 NonRepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
657 if NonRepeatPlaceHolders
:
659 for S
in self
._SubSectionList
:
660 if S
not in NonRepeatPlaceHolders
:
663 StringList
.append(str(NonRepeatPlaceHolders
[S
]))
665 StringList
= self
._SubSectionList
667 if RepeatPlaceHolders
:
669 for Index
in range(RepeatTime
):
671 if S
not in RepeatPlaceHolders
:
672 TempStringList
.append(S
)
674 TempStringList
.append(str(RepeatPlaceHolders
[S
][Index
]))
675 StringList
= TempStringList
677 return "".join(StringList
)
680 def __init__(self
, Template
=None):
682 self
._Template
= Template
683 self
._TemplateSectionList
= self
._Parse
(Template
)
687 # @retval string The string replaced
692 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
694 # @retval list A list of TemplateString.Section objects
696 def _Parse(self
, Template
):
701 TemplateSectionList
= []
703 MatchObj
= gPlaceholderPattern
.search(Template
, SearchFrom
)
705 if MatchEnd
< len(Template
):
706 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:], PlaceHolderList
)
707 TemplateSectionList
.append(TemplateSection
)
710 MatchString
= MatchObj
.group(1)
711 MatchStart
= MatchObj
.start()
712 MatchEnd
= MatchObj
.end()
714 if MatchString
== self
._REPEAT
_START
_FLAG
:
715 if MatchStart
> SectionStart
:
716 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
717 TemplateSectionList
.append(TemplateSection
)
718 SectionStart
= MatchEnd
720 elif MatchString
== self
._REPEAT
_END
_FLAG
:
721 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
722 TemplateSectionList
.append(TemplateSection
)
723 SectionStart
= MatchEnd
726 PlaceHolderList
.append((MatchString
, MatchStart
- SectionStart
, MatchEnd
- SectionStart
))
727 SearchFrom
= MatchEnd
728 return TemplateSectionList
730 ## Replace the string template with dictionary of placeholders and append it to previous one
732 # @param AppendString The string template to append
733 # @param Dictionary The placeholder dictionaries
735 def Append(self
, AppendString
, Dictionary
=None):
737 SectionList
= self
._Parse
(AppendString
)
738 self
.String
+= "".join([S
.Instantiate(Dictionary
) for S
in SectionList
])
740 self
.String
+= AppendString
742 ## Replace the string template with dictionary of placeholders
744 # @param Dictionary The placeholder dictionaries
746 # @retval str The string replaced with placeholder values
748 def Replace(self
, Dictionary
=None):
749 return "".join([S
.Instantiate(Dictionary
) for S
in self
._TemplateSectionList
])
751 ## Progress indicator class
753 # This class makes use of thread to print progress on console.
756 # for avoiding deadloop
758 _ProgressThread
= None
759 _CheckInterval
= 0.25
763 # @param OpenMessage The string printed before progress charaters
764 # @param CloseMessage The string printed after progress charaters
765 # @param ProgressChar The charater used to indicate the progress
766 # @param Interval The interval in seconds between two progress charaters
768 def __init__(self
, OpenMessage
="", CloseMessage
="", ProgressChar
='.', Interval
=1.0):
769 self
.PromptMessage
= OpenMessage
770 self
.CodaMessage
= CloseMessage
771 self
.ProgressChar
= ProgressChar
772 self
.Interval
= Interval
773 if Progressor
._StopFlag
== None:
774 Progressor
._StopFlag
= threading
.Event()
776 ## Start to print progress charater
778 # @param OpenMessage The string printed before progress charaters
780 def Start(self
, OpenMessage
=None):
781 if OpenMessage
!= None:
782 self
.PromptMessage
= OpenMessage
783 Progressor
._StopFlag
.clear()
784 if Progressor
._ProgressThread
== None:
785 Progressor
._ProgressThread
= threading
.Thread(target
=self
._ProgressThreadEntry
)
786 Progressor
._ProgressThread
.setDaemon(False)
787 Progressor
._ProgressThread
.start()
789 ## Stop printing progress charater
791 # @param CloseMessage The string printed after progress charaters
793 def Stop(self
, CloseMessage
=None):
794 OriginalCodaMessage
= self
.CodaMessage
795 if CloseMessage
!= None:
796 self
.CodaMessage
= CloseMessage
798 self
.CodaMessage
= OriginalCodaMessage
800 ## Thread entry method
801 def _ProgressThreadEntry(self
):
802 sys
.stdout
.write(self
.PromptMessage
+ " ")
805 while not Progressor
._StopFlag
.isSet():
807 sys
.stdout
.write(self
.ProgressChar
)
809 TimeUp
= self
.Interval
810 time
.sleep(self
._CheckInterval
)
811 TimeUp
-= self
._CheckInterval
812 sys
.stdout
.write(" " + self
.CodaMessage
+ "\n")
815 ## Abort the progress display
818 if Progressor
._StopFlag
!= None:
819 Progressor
._StopFlag
.set()
820 if Progressor
._ProgressThread
!= None:
821 Progressor
._ProgressThread
.join()
822 Progressor
._ProgressThread
= None
824 ## A dict which can access its keys and/or values orderly
826 # The class implements a new kind of dict which its keys or values can be
827 # accessed in the order they are added into the dict. It guarantees the order
828 # by making use of an internal list to keep a copy of keys.
830 class sdict(IterableUserDict
):
833 IterableUserDict
.__init
__(self
)
837 def __setitem__(self
, key
, value
):
838 if key
not in self
._key
_list
:
839 self
._key
_list
.append(key
)
840 IterableUserDict
.__setitem
__(self
, key
, value
)
843 def __delitem__(self
, key
):
844 self
._key
_list
.remove(key
)
845 IterableUserDict
.__delitem
__(self
, key
)
847 ## used in "for k in dict" loop to ensure the correct order
849 return self
.iterkeys()
853 return len(self
._key
_list
)
856 def __contains__(self
, key
):
857 return key
in self
._key
_list
860 def index(self
, key
):
861 return self
._key
_list
.index(key
)
864 def insert(self
, key
, newkey
, newvalue
, order
):
865 index
= self
._key
_list
.index(key
)
866 if order
== 'BEFORE':
867 self
._key
_list
.insert(index
, newkey
)
868 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
869 elif order
== 'AFTER':
870 self
._key
_list
.insert(index
+ 1, newkey
)
871 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
874 def append(self
, sdict
):
876 if key
not in self
._key
_list
:
877 self
._key
_list
.append(key
)
878 IterableUserDict
.__setitem
__(self
, key
, sdict
[key
])
880 def has_key(self
, key
):
881 return key
in self
._key
_list
886 IterableUserDict
.clear(self
)
888 ## Return a copy of keys
891 for key
in self
._key
_list
:
895 ## Return a copy of values
898 for key
in self
._key
_list
:
899 values
.append(self
[key
])
902 ## Return a copy of (key, value) list
905 for key
in self
._key
_list
:
906 items
.append((key
, self
[key
]))
911 return iter(self
.items())
913 ## Keys interation support
915 return iter(self
.keys())
917 ## Values interation support
918 def itervalues(self
):
919 return iter(self
.values())
921 ## Return value related to a key, and remove the (key, value) from the dict
922 def pop(self
, key
, *dv
):
924 if key
in self
._key
_list
:
926 self
.__delitem
__(key
)
931 ## Return (key, value) pair, and remove the (key, value) from the dict
933 key
= self
._key
_list
[-1]
935 self
.__delitem
__(key
)
938 def update(self
, dict=None, **kwargs
):
940 for k
, v
in dict.items():
943 for k
, v
in kwargs
.items():
946 ## Dictionary with restricted keys
950 def __init__(self
, KeyList
):
952 dict.__setitem
__(self
, Key
, "")
955 def __setitem__(self
, key
, value
):
957 EdkLogger
.error("RestrictedDict", ATTRIBUTE_SET_FAILURE
, "Key [%s] is not allowed" % key
,
958 ExtraData
=", ".join(dict.keys(self
)))
959 dict.__setitem
__(self
, key
, value
)
962 def __getitem__(self
, key
):
965 return dict.__getitem
__(self
, key
)
968 def __delitem__(self
, key
):
969 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="del")
974 self
.__setitem
__(Key
, "")
976 ## Return value related to a key, and remove the (key, value) from the dict
977 def pop(self
, key
, *dv
):
978 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="pop")
980 ## Return (key, value) pair, and remove the (key, value) from the dict
982 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="popitem")
984 ## Dictionary using prioritized list as key
988 _TupleType
= type(())
990 _ValidWildcardList
= ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
992 def __init__(self
, _Single_
=False, _Level_
=2):
993 self
._Level
_ = _Level_
995 self
._Single
_ = _Single_
998 def __getitem__(self
, key
):
1001 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1005 elif self
._Level
_ > 1:
1006 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1009 if self
._Level
_ > 1:
1010 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1012 if FirstKey
== None or str(FirstKey
).upper() in self
._ValidWildcardList
:
1013 FirstKey
= self
._Wildcard
1016 return self
._GetSingleValue
(FirstKey
, RestKeys
)
1018 return self
._GetAllValues
(FirstKey
, RestKeys
)
1020 def _GetSingleValue(self
, FirstKey
, RestKeys
):
1022 #print "%s-%s" % (FirstKey, self._Level_) ,
1023 if self
._Level
_ > 1:
1024 if FirstKey
== self
._Wildcard
:
1025 if FirstKey
in self
.data
:
1026 Value
= self
.data
[FirstKey
][RestKeys
]
1028 for Key
in self
.data
:
1029 Value
= self
.data
[Key
][RestKeys
]
1030 if Value
!= None: break
1032 if FirstKey
in self
.data
:
1033 Value
= self
.data
[FirstKey
][RestKeys
]
1034 if Value
== None and self
._Wildcard
in self
.data
:
1036 Value
= self
.data
[self
._Wildcard
][RestKeys
]
1038 if FirstKey
== self
._Wildcard
:
1039 if FirstKey
in self
.data
:
1040 Value
= self
.data
[FirstKey
]
1042 for Key
in self
.data
:
1043 Value
= self
.data
[Key
]
1044 if Value
!= None: break
1046 if FirstKey
in self
.data
:
1047 Value
= self
.data
[FirstKey
]
1048 elif self
._Wildcard
in self
.data
:
1049 Value
= self
.data
[self
._Wildcard
]
1052 def _GetAllValues(self
, FirstKey
, RestKeys
):
1054 if self
._Level
_ > 1:
1055 if FirstKey
== self
._Wildcard
:
1056 for Key
in self
.data
:
1057 Value
+= self
.data
[Key
][RestKeys
]
1059 if FirstKey
in self
.data
:
1060 Value
+= self
.data
[FirstKey
][RestKeys
]
1061 if self
._Wildcard
in self
.data
:
1062 Value
+= self
.data
[self
._Wildcard
][RestKeys
]
1064 if FirstKey
== self
._Wildcard
:
1065 for Key
in self
.data
:
1066 Value
.append(self
.data
[Key
])
1068 if FirstKey
in self
.data
:
1069 Value
.append(self
.data
[FirstKey
])
1070 if self
._Wildcard
in self
.data
:
1071 Value
.append(self
.data
[self
._Wildcard
])
1075 def __setitem__(self
, key
, value
):
1078 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1083 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1086 if self
._Level
_ > 1:
1087 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1089 if FirstKey
in self
._ValidWildcardList
:
1090 FirstKey
= self
._Wildcard
1092 if FirstKey
not in self
.data
and self
._Level
_ > 0:
1093 self
.data
[FirstKey
] = tdict(self
._Single
_, self
._Level
_ - 1)
1095 if self
._Level
_ > 1:
1096 self
.data
[FirstKey
][RestKeys
] = value
1098 self
.data
[FirstKey
] = value
1100 def SetGreedyMode(self
):
1101 self
._Single
_ = False
1102 if self
._Level
_ > 1:
1103 for Key
in self
.data
:
1104 self
.data
[Key
].SetGreedyMode()
1106 def SetSingleMode(self
):
1107 self
._Single
_ = True
1108 if self
._Level
_ > 1:
1109 for Key
in self
.data
:
1110 self
.data
[Key
].SetSingleMode()
1112 ## Boolean chain list
1114 class Blist(UserList
):
1115 def __init__(self
, initlist
=None):
1116 UserList
.__init
__(self
, initlist
)
1117 def __setitem__(self
, i
, item
):
1118 if item
not in [True, False]:
1124 def _GetResult(self
):
1126 for item
in self
.data
:
1129 Result
= property(_GetResult
)
1131 def ParseConsoleLog(Filename
):
1132 Opr
= open(os
.path
.normpath(Filename
), 'r')
1133 Opw
= open(os
.path
.normpath(Filename
+ '.New'), 'w+')
1134 for Line
in Opr
.readlines():
1135 if Line
.find('.efi') > -1:
1136 Line
= Line
[Line
.rfind(' ') : Line
.rfind('.efi')].strip()
1137 Opw
.write('%s\n' % Line
)
1142 ## check format of PCD value against its the datum type
1144 # For PCD value setting
1146 def CheckPcdDatum(Type
, Value
):
1148 if not ((Value
.startswith('L"') or Value
.startswith('"') and Value
.endswith('"'))
1149 or (Value
.startswith('{') and Value
.endswith('}'))
1151 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1152 ", or \"...\" for string, or L\"...\" for unicode string" % (Value
, Type
)
1153 elif Type
== 'BOOLEAN':
1154 if Value
not in ['TRUE', 'FALSE']:
1155 return False, "Invalid value [%s] of type [%s]; must be TRUE or FALSE" % (Value
, Type
)
1156 elif type(Value
) == type(""):
1158 Value
= long(Value
, 0)
1160 return False, "Invalid value [%s] of type [%s];"\
1161 " must be a hexadecimal, decimal or octal in C language format."\
1166 ## Split command line option string to list
1168 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1169 # in non-windows platform to launch command
1171 def SplitOption(OptionString
):
1176 for Index
in range(0, len(OptionString
)):
1177 CurrentChar
= OptionString
[Index
]
1178 if CurrentChar
in ['"', "'"]:
1179 if QuotationMark
== CurrentChar
:
1181 elif QuotationMark
== "":
1182 QuotationMark
= CurrentChar
1187 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
1188 if Index
> OptionStart
:
1189 OptionList
.append(OptionString
[OptionStart
:Index
-1])
1191 LastChar
= CurrentChar
1192 OptionList
.append(OptionString
[OptionStart
:])
1195 def CommonPath(PathList
):
1196 P1
= min(PathList
).split(os
.path
.sep
)
1197 P2
= max(PathList
).split(os
.path
.sep
)
1198 for Index
in xrange(min(len(P1
), len(P2
))):
1199 if P1
[Index
] != P2
[Index
]:
1200 return os
.path
.sep
.join(P1
[:Index
])
1201 return os
.path
.sep
.join(P1
)
1203 class PathClass(object):
1204 def __init__(self
, File
='', Root
='', AlterRoot
='', Type
='', IsBinary
=False,
1205 Arch
='COMMON', ToolChainFamily
='', Target
='', TagName
='', ToolCode
=''):
1207 self
.File
= str(File
)
1208 if os
.path
.isabs(self
.File
):
1212 self
.Root
= str(Root
)
1213 self
.AlterRoot
= str(AlterRoot
)
1215 # Remove any '.' and '..' in path
1217 self
.Path
= os
.path
.normpath(os
.path
.join(self
.Root
, self
.File
))
1218 self
.Root
= os
.path
.normpath(CommonPath([self
.Root
, self
.Path
]))
1219 # eliminate the side-effect of 'C:'
1220 if self
.Root
[-1] == ':':
1221 self
.Root
+= os
.path
.sep
1222 # file path should not start with path separator
1223 if self
.Root
[-1] == os
.path
.sep
:
1224 self
.File
= self
.Path
[len(self
.Root
):]
1226 self
.File
= self
.Path
[len(self
.Root
)+1:]
1228 self
.Path
= os
.path
.normpath(self
.File
)
1230 self
.SubDir
, self
.Name
= os
.path
.split(self
.File
)
1231 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1235 self
.Dir
= os
.path
.join(self
.Root
, self
.SubDir
)
1237 self
.Dir
= self
.Root
1239 self
.Dir
= self
.SubDir
1244 self
.Type
= self
.Ext
.lower()
1246 self
.IsBinary
= IsBinary
1247 self
.Target
= Target
1248 self
.TagName
= TagName
1249 self
.ToolCode
= ToolCode
1250 self
.ToolChainFamily
= ToolChainFamily
1254 ## Convert the object of this class to a string
1256 # Convert member Path of the class to a string
1258 # @retval string Formatted String
1263 ## Override __eq__ function
1265 # Check whether PathClass are the same
1267 # @retval False The two PathClass are different
1268 # @retval True The two PathClass are the same
1270 def __eq__(self
, Other
):
1271 if type(Other
) == type(self
):
1272 return self
.Path
== Other
.Path
1274 return self
.Path
== str(Other
)
1276 ## Override __hash__ function
1278 # Use Path as key in hash table
1280 # @retval string Key for hash table
1283 return hash(self
.Path
)
1285 def _GetFileKey(self
):
1286 if self
._Key
== None:
1287 self
._Key
= self
.Path
.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1290 def Validate(self
, Type
='', CaseSensitive
=True):
1291 if GlobalData
.gCaseInsensitive
:
1292 CaseSensitive
= False
1293 if Type
and Type
.lower() != self
.Type
:
1294 return FILE_TYPE_MISMATCH
, '%s (expect %s but got %s)' % (self
.File
, Type
, self
.Type
)
1296 RealFile
, RealRoot
= RealPath2(self
.File
, self
.Root
, self
.AlterRoot
)
1297 if not RealRoot
and not RealFile
:
1298 return FILE_NOT_FOUND
, self
.File
1302 if RealRoot
!= self
.Root
or RealFile
!= self
.File
:
1303 if CaseSensitive
and (RealFile
!= self
.File
or (RealRoot
!= self
.Root
and RealRoot
!= self
.AlterRoot
)):
1304 ErrorCode
= FILE_CASE_MISMATCH
1305 ErrorInfo
= self
.File
+ '\n\t' + RealFile
+ " [in file system]"
1307 self
.SubDir
, self
.Name
= os
.path
.split(RealFile
)
1308 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1310 self
.Dir
= os
.path
.join(RealRoot
, self
.SubDir
)
1313 self
.File
= RealFile
1314 self
.Root
= RealRoot
1315 self
.Path
= os
.path
.join(RealRoot
, RealFile
)
1316 return ErrorCode
, ErrorInfo
1318 Key
= property(_GetFileKey
)
1322 # This acts like the main() function for the script, unless it is 'import'ed into another
1325 if __name__
== '__main__':