]>
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
322 def __init__(self
, Root
):
324 for F
in os
.listdir(Root
):
326 self
._UPPER
_CACHE
_[F
.upper()] = F
329 def __getitem__(self
, Path
):
330 Path
= Path
[len(os
.path
.commonprefix([Path
, self
._Root
])):]
333 if Path
and Path
[0] == os
.path
.sep
:
335 if Path
in self
._CACHE
_:
336 return os
.path
.join(self
._Root
, Path
)
337 UpperPath
= Path
.upper()
338 if UpperPath
in self
._UPPER
_CACHE
_:
339 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
343 SepIndex
= Path
.find(os
.path
.sep
)
345 Parent
= UpperPath
[:SepIndex
]
346 if Parent
not in self
._UPPER
_CACHE
_:
348 LastSepIndex
= SepIndex
349 SepIndex
= Path
.find(os
.path
.sep
, LastSepIndex
+ 1)
351 if LastSepIndex
== -1:
356 SepIndex
= LastSepIndex
358 Parent
= Path
[:SepIndex
]
359 ParentKey
= UpperPath
[:SepIndex
]
360 if ParentKey
not in self
._UPPER
_CACHE
_:
364 if Parent
in self
._CACHE
_:
367 ParentDir
= self
._UPPER
_CACHE
_[ParentKey
]
368 for F
in os
.listdir(ParentDir
):
369 Dir
= os
.path
.join(ParentDir
, F
)
370 self
._CACHE
_.add(Dir
)
371 self
._UPPER
_CACHE
_[Dir
.upper()] = Dir
373 SepIndex
= Path
.find(os
.path
.sep
, SepIndex
+ 1)
376 if Path
in self
._CACHE
_:
377 return os
.path
.join(self
._Root
, Path
)
378 elif UpperPath
in self
._UPPER
_CACHE
_:
379 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
382 ## Get all files of a directory
384 # @param Root: Root dir
385 # @param SkipList : The files need be skipped
387 # @retval A list of all files
389 def GetFiles(Root
, SkipList
=None, FullPath
= True):
392 for Root
, Dirs
, Files
in os
.walk(Root
):
394 for Item
in SkipList
:
399 File
= os
.path
.normpath(os
.path
.join(Root
, File
))
401 File
= File
[len(OriPath
) + 1:]
402 FileList
.append(File
)
406 ## Check if gvien file exists or not
408 # @param File File name or path to be checked
409 # @param Dir The directory the file is relative to
411 # @retval True if file exists
412 # @retval False if file doesn't exists
414 def ValidFile(File
, Ext
=None):
416 Dummy
, FileExt
= os
.path
.splitext(File
)
417 if FileExt
.lower() != Ext
.lower():
419 if not os
.path
.exists(File
):
423 def RealPath(File
, Dir
='', OverrideDir
=''):
424 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
425 NewFile
= GlobalData
.gAllFiles
[NewFile
]
426 if not NewFile
and OverrideDir
:
427 NewFile
= os
.path
.normpath(os
.path
.join(OverrideDir
, File
))
428 NewFile
= GlobalData
.gAllFiles
[NewFile
]
431 def RealPath2(File
, Dir
='', OverrideDir
=''):
433 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
435 if OverrideDir
[-1] == os
.path
.sep
:
436 return NewFile
[len(OverrideDir
):], NewFile
[0:len(OverrideDir
)]
438 return NewFile
[len(OverrideDir
)+1:], NewFile
[0:len(OverrideDir
)]
440 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
443 if Dir
[-1] == os
.path
.sep
:
444 return NewFile
[len(Dir
):], NewFile
[0:len(Dir
)]
446 return NewFile
[len(Dir
)+1:], NewFile
[0:len(Dir
)]
452 ## Check if gvien file exists or not
455 def ValidFile2(AllFiles
, File
, Ext
=None, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
458 Dummy
, FileExt
= os
.path
.splitext(File
)
459 if FileExt
.lower() != Ext
.lower():
462 # Replace the R8 macros
463 if OverrideDir
!= '' and OverrideDir
!= None:
464 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
465 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
466 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
467 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
469 # Replace the default dir to current dir
472 Dir
= Dir
[len(Workspace
)+1:]
474 # First check if File has R8 definition itself
475 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
476 NewFile
= File
.replace('$(EFI_SOURCE)', EfiSource
)
477 NewFile
= NewFile
.replace('$(EDK_SOURCE)', EdkSource
)
478 NewFile
= AllFiles
[os
.path
.normpath(NewFile
)]
482 # Second check the path with override value
483 if OverrideDir
!= '' and OverrideDir
!= None:
484 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
488 # Last check the path with normal definitions
489 File
= os
.path
.join(Dir
, File
)
490 NewFile
= AllFiles
[os
.path
.normpath(File
)]
496 ## Check if gvien file exists or not
499 def ValidFile3(AllFiles
, File
, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
500 # Replace the R8 macros
501 if OverrideDir
!= '' and OverrideDir
!= None:
502 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
503 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
504 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
505 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
507 # Replace the default dir to current dir
508 # Dir is current module dir related to workspace
511 Dir
= Dir
[len(Workspace
)+1:]
514 RelaPath
= AllFiles
[os
.path
.normpath(Dir
)]
515 NewRelaPath
= RelaPath
518 # First check if File has R8 definition itself
519 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
520 File
= File
.replace('$(EFI_SOURCE)', EfiSource
)
521 File
= File
.replace('$(EDK_SOURCE)', EdkSource
)
522 NewFile
= AllFiles
[os
.path
.normpath(File
)]
524 NewRelaPath
= os
.path
.dirname(NewFile
)
525 File
= os
.path
.basename(NewFile
)
526 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
529 # Second check the path with override value
530 if OverrideDir
!= '' and OverrideDir
!= None:
531 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
533 #NewRelaPath = os.path.dirname(NewFile)
534 NewRelaPath
= NewFile
[:len(NewFile
) - len(File
.replace("..\\", '').replace("../", '')) - 1]
537 # Last check the path with normal definitions
538 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
545 return NewRelaPath
, RelaPath
, File
548 def GetRelPath(Path1
, Path2
):
549 FileName
= os
.path
.basename(Path2
)
550 L1
= os
.path
.normpath(Path1
).split(os
.path
.normpath('/'))
551 L2
= os
.path
.normpath(Path2
).split(os
.path
.normpath('/'))
552 for Index
in range(0, len(L1
)):
553 if L1
[Index
] != L2
[Index
]:
554 FileName
= '../' * (len(L1
) - Index
)
555 for Index2
in range(Index
, len(L2
)):
556 FileName
= os
.path
.join(FileName
, L2
[Index2
])
558 return os
.path
.normpath(FileName
)
561 ## Get GUID value from given packages
563 # @param CName The CName of the GUID
564 # @param PackageList List of packages looking-up in
566 # @retval GuidValue if the CName is found in any given package
567 # @retval None if the CName is not found in all given packages
569 def GuidValue(CName
, PackageList
):
570 for P
in PackageList
:
572 return P
.Guids
[CName
]
575 ## Get Protocol value from given packages
577 # @param CName The CName of the GUID
578 # @param PackageList List of packages looking-up in
580 # @retval GuidValue if the CName is found in any given package
581 # @retval None if the CName is not found in all given packages
583 def ProtocolValue(CName
, PackageList
):
584 for P
in PackageList
:
585 if CName
in P
.Protocols
:
586 return P
.Protocols
[CName
]
589 ## Get PPI value from given packages
591 # @param CName The CName of the GUID
592 # @param PackageList List of packages looking-up in
594 # @retval GuidValue if the CName is found in any given package
595 # @retval None if the CName is not found in all given packages
597 def PpiValue(CName
, PackageList
):
598 for P
in PackageList
:
603 ## A string template class
605 # This class implements a template for string replacement. A string template
606 # looks like following
608 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
610 # The string between ${BEGIN} and ${END} will be repeated as many times as the
611 # length of "placeholder_name", which is a list passed through a dict. The
612 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
613 # be not used and, in this case, the "placeholder_name" must not a list and it
614 # will just be replaced once.
616 class TemplateString(object):
617 _REPEAT_START_FLAG
= "BEGIN"
618 _REPEAT_END_FLAG
= "END"
620 class Section(object):
621 _LIST_TYPES
= [type([]), type(set()), type((0,))]
623 def __init__(self
, TemplateSection
, PlaceHolderList
):
624 self
._Template
= TemplateSection
625 self
._PlaceHolderList
= []
627 # Split the section into sub-sections according to the position of placeholders
629 self
._SubSectionList
= []
632 # The placeholders passed in must be in the format of
634 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
636 for PlaceHolder
,Start
,End
in PlaceHolderList
:
637 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:Start
])
638 self
._SubSectionList
.append(TemplateSection
[Start
:End
])
639 self
._PlaceHolderList
.append(PlaceHolder
)
640 SubSectionStart
= End
641 if SubSectionStart
< len(TemplateSection
):
642 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:])
644 self
._SubSectionList
= [TemplateSection
]
647 return self
._Template
+ " : " + str(self
._PlaceHolderList
)
649 def Instantiate(self
, PlaceHolderValues
):
651 RepeatPlaceHolders
= {}
652 NonRepeatPlaceHolders
= {}
654 for PlaceHolder
in self
._PlaceHolderList
:
655 if PlaceHolder
not in PlaceHolderValues
:
657 Value
= PlaceHolderValues
[PlaceHolder
]
658 if type(Value
) in self
._LIST
_TYPES
:
660 RepeatTime
= len(Value
)
661 elif RepeatTime
!= len(Value
):
665 "${%s} has different repeat time from others!" % PlaceHolder
,
666 ExtraData
=str(self
._Template
)
668 RepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
670 NonRepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
672 if NonRepeatPlaceHolders
:
674 for S
in self
._SubSectionList
:
675 if S
not in NonRepeatPlaceHolders
:
678 StringList
.append(str(NonRepeatPlaceHolders
[S
]))
680 StringList
= self
._SubSectionList
682 if RepeatPlaceHolders
:
684 for Index
in range(RepeatTime
):
686 if S
not in RepeatPlaceHolders
:
687 TempStringList
.append(S
)
689 TempStringList
.append(str(RepeatPlaceHolders
[S
][Index
]))
690 StringList
= TempStringList
692 return "".join(StringList
)
695 def __init__(self
, Template
=None):
697 self
.IsBinary
= False
698 self
._Template
= Template
699 self
._TemplateSectionList
= self
._Parse
(Template
)
703 # @retval string The string replaced
708 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
710 # @retval list A list of TemplateString.Section objects
712 def _Parse(self
, Template
):
717 TemplateSectionList
= []
719 MatchObj
= gPlaceholderPattern
.search(Template
, SearchFrom
)
721 if MatchEnd
< len(Template
):
722 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:], PlaceHolderList
)
723 TemplateSectionList
.append(TemplateSection
)
726 MatchString
= MatchObj
.group(1)
727 MatchStart
= MatchObj
.start()
728 MatchEnd
= MatchObj
.end()
730 if MatchString
== self
._REPEAT
_START
_FLAG
:
731 if MatchStart
> SectionStart
:
732 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
733 TemplateSectionList
.append(TemplateSection
)
734 SectionStart
= MatchEnd
736 elif MatchString
== self
._REPEAT
_END
_FLAG
:
737 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
738 TemplateSectionList
.append(TemplateSection
)
739 SectionStart
= MatchEnd
742 PlaceHolderList
.append((MatchString
, MatchStart
- SectionStart
, MatchEnd
- SectionStart
))
743 SearchFrom
= MatchEnd
744 return TemplateSectionList
746 ## Replace the string template with dictionary of placeholders and append it to previous one
748 # @param AppendString The string template to append
749 # @param Dictionary The placeholder dictionaries
751 def Append(self
, AppendString
, Dictionary
=None):
753 SectionList
= self
._Parse
(AppendString
)
754 self
.String
+= "".join([S
.Instantiate(Dictionary
) for S
in SectionList
])
756 self
.String
+= AppendString
758 ## Replace the string template with dictionary of placeholders
760 # @param Dictionary The placeholder dictionaries
762 # @retval str The string replaced with placeholder values
764 def Replace(self
, Dictionary
=None):
765 return "".join([S
.Instantiate(Dictionary
) for S
in self
._TemplateSectionList
])
767 ## Progress indicator class
769 # This class makes use of thread to print progress on console.
772 # for avoiding deadloop
774 _ProgressThread
= None
775 _CheckInterval
= 0.25
779 # @param OpenMessage The string printed before progress charaters
780 # @param CloseMessage The string printed after progress charaters
781 # @param ProgressChar The charater used to indicate the progress
782 # @param Interval The interval in seconds between two progress charaters
784 def __init__(self
, OpenMessage
="", CloseMessage
="", ProgressChar
='.', Interval
=1.0):
785 self
.PromptMessage
= OpenMessage
786 self
.CodaMessage
= CloseMessage
787 self
.ProgressChar
= ProgressChar
788 self
.Interval
= Interval
789 if Progressor
._StopFlag
== None:
790 Progressor
._StopFlag
= threading
.Event()
792 ## Start to print progress charater
794 # @param OpenMessage The string printed before progress charaters
796 def Start(self
, OpenMessage
=None):
797 if OpenMessage
!= None:
798 self
.PromptMessage
= OpenMessage
799 Progressor
._StopFlag
.clear()
800 if Progressor
._ProgressThread
== None:
801 Progressor
._ProgressThread
= threading
.Thread(target
=self
._ProgressThreadEntry
)
802 Progressor
._ProgressThread
.setDaemon(False)
803 Progressor
._ProgressThread
.start()
805 ## Stop printing progress charater
807 # @param CloseMessage The string printed after progress charaters
809 def Stop(self
, CloseMessage
=None):
810 OriginalCodaMessage
= self
.CodaMessage
811 if CloseMessage
!= None:
812 self
.CodaMessage
= CloseMessage
814 self
.CodaMessage
= OriginalCodaMessage
816 ## Thread entry method
817 def _ProgressThreadEntry(self
):
818 sys
.stdout
.write(self
.PromptMessage
+ " ")
821 while not Progressor
._StopFlag
.isSet():
823 sys
.stdout
.write(self
.ProgressChar
)
825 TimeUp
= self
.Interval
826 time
.sleep(self
._CheckInterval
)
827 TimeUp
-= self
._CheckInterval
828 sys
.stdout
.write(" " + self
.CodaMessage
+ "\n")
831 ## Abort the progress display
834 if Progressor
._StopFlag
!= None:
835 Progressor
._StopFlag
.set()
836 if Progressor
._ProgressThread
!= None:
837 Progressor
._ProgressThread
.join()
838 Progressor
._ProgressThread
= None
840 ## A dict which can access its keys and/or values orderly
842 # The class implements a new kind of dict which its keys or values can be
843 # accessed in the order they are added into the dict. It guarantees the order
844 # by making use of an internal list to keep a copy of keys.
846 class sdict(IterableUserDict
):
849 IterableUserDict
.__init
__(self
)
853 def __setitem__(self
, key
, value
):
854 if key
not in self
._key
_list
:
855 self
._key
_list
.append(key
)
856 IterableUserDict
.__setitem
__(self
, key
, value
)
859 def __delitem__(self
, key
):
860 self
._key
_list
.remove(key
)
861 IterableUserDict
.__delitem
__(self
, key
)
863 ## used in "for k in dict" loop to ensure the correct order
865 return self
.iterkeys()
869 return len(self
._key
_list
)
872 def __contains__(self
, key
):
873 return key
in self
._key
_list
876 def index(self
, key
):
877 return self
._key
_list
.index(key
)
880 def insert(self
, key
, newkey
, newvalue
, order
):
881 index
= self
._key
_list
.index(key
)
882 if order
== 'BEFORE':
883 self
._key
_list
.insert(index
, newkey
)
884 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
885 elif order
== 'AFTER':
886 self
._key
_list
.insert(index
+ 1, newkey
)
887 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
890 def append(self
, sdict
):
892 if key
not in self
._key
_list
:
893 self
._key
_list
.append(key
)
894 IterableUserDict
.__setitem
__(self
, key
, sdict
[key
])
896 def has_key(self
, key
):
897 return key
in self
._key
_list
902 IterableUserDict
.clear(self
)
904 ## Return a copy of keys
907 for key
in self
._key
_list
:
911 ## Return a copy of values
914 for key
in self
._key
_list
:
915 values
.append(self
[key
])
918 ## Return a copy of (key, value) list
921 for key
in self
._key
_list
:
922 items
.append((key
, self
[key
]))
927 return iter(self
.items())
929 ## Keys interation support
931 return iter(self
.keys())
933 ## Values interation support
934 def itervalues(self
):
935 return iter(self
.values())
937 ## Return value related to a key, and remove the (key, value) from the dict
938 def pop(self
, key
, *dv
):
940 if key
in self
._key
_list
:
942 self
.__delitem
__(key
)
947 ## Return (key, value) pair, and remove the (key, value) from the dict
949 key
= self
._key
_list
[-1]
951 self
.__delitem
__(key
)
954 def update(self
, dict=None, **kwargs
):
956 for k
, v
in dict.items():
959 for k
, v
in kwargs
.items():
962 ## Dictionary with restricted keys
966 def __init__(self
, KeyList
):
968 dict.__setitem
__(self
, Key
, "")
971 def __setitem__(self
, key
, value
):
973 EdkLogger
.error("RestrictedDict", ATTRIBUTE_SET_FAILURE
, "Key [%s] is not allowed" % key
,
974 ExtraData
=", ".join(dict.keys(self
)))
975 dict.__setitem
__(self
, key
, value
)
978 def __getitem__(self
, key
):
981 return dict.__getitem
__(self
, key
)
984 def __delitem__(self
, key
):
985 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="del")
990 self
.__setitem
__(Key
, "")
992 ## Return value related to a key, and remove the (key, value) from the dict
993 def pop(self
, key
, *dv
):
994 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="pop")
996 ## Return (key, value) pair, and remove the (key, value) from the dict
998 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="popitem")
1000 ## Dictionary using prioritized list as key
1003 _ListType
= type([])
1004 _TupleType
= type(())
1005 _Wildcard
= 'COMMON'
1006 _ValidWildcardList
= ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1008 def __init__(self
, _Single_
=False, _Level_
=2):
1009 self
._Level
_ = _Level_
1011 self
._Single
_ = _Single_
1014 def __getitem__(self
, key
):
1017 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1021 elif self
._Level
_ > 1:
1022 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1025 if self
._Level
_ > 1:
1026 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1028 if FirstKey
== None or str(FirstKey
).upper() in self
._ValidWildcardList
:
1029 FirstKey
= self
._Wildcard
1032 return self
._GetSingleValue
(FirstKey
, RestKeys
)
1034 return self
._GetAllValues
(FirstKey
, RestKeys
)
1036 def _GetSingleValue(self
, FirstKey
, RestKeys
):
1038 #print "%s-%s" % (FirstKey, self._Level_) ,
1039 if self
._Level
_ > 1:
1040 if FirstKey
== self
._Wildcard
:
1041 if FirstKey
in self
.data
:
1042 Value
= self
.data
[FirstKey
][RestKeys
]
1044 for Key
in self
.data
:
1045 Value
= self
.data
[Key
][RestKeys
]
1046 if Value
!= None: break
1048 if FirstKey
in self
.data
:
1049 Value
= self
.data
[FirstKey
][RestKeys
]
1050 if Value
== None and self
._Wildcard
in self
.data
:
1052 Value
= self
.data
[self
._Wildcard
][RestKeys
]
1054 if FirstKey
== self
._Wildcard
:
1055 if FirstKey
in self
.data
:
1056 Value
= self
.data
[FirstKey
]
1058 for Key
in self
.data
:
1059 Value
= self
.data
[Key
]
1060 if Value
!= None: break
1062 if FirstKey
in self
.data
:
1063 Value
= self
.data
[FirstKey
]
1064 elif self
._Wildcard
in self
.data
:
1065 Value
= self
.data
[self
._Wildcard
]
1068 def _GetAllValues(self
, FirstKey
, RestKeys
):
1070 if self
._Level
_ > 1:
1071 if FirstKey
== self
._Wildcard
:
1072 for Key
in self
.data
:
1073 Value
+= self
.data
[Key
][RestKeys
]
1075 if FirstKey
in self
.data
:
1076 Value
+= self
.data
[FirstKey
][RestKeys
]
1077 if self
._Wildcard
in self
.data
:
1078 Value
+= self
.data
[self
._Wildcard
][RestKeys
]
1080 if FirstKey
== self
._Wildcard
:
1081 for Key
in self
.data
:
1082 Value
.append(self
.data
[Key
])
1084 if FirstKey
in self
.data
:
1085 Value
.append(self
.data
[FirstKey
])
1086 if self
._Wildcard
in self
.data
:
1087 Value
.append(self
.data
[self
._Wildcard
])
1091 def __setitem__(self
, key
, value
):
1094 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1099 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1102 if self
._Level
_ > 1:
1103 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1105 if FirstKey
in self
._ValidWildcardList
:
1106 FirstKey
= self
._Wildcard
1108 if FirstKey
not in self
.data
and self
._Level
_ > 0:
1109 self
.data
[FirstKey
] = tdict(self
._Single
_, self
._Level
_ - 1)
1111 if self
._Level
_ > 1:
1112 self
.data
[FirstKey
][RestKeys
] = value
1114 self
.data
[FirstKey
] = value
1116 def SetGreedyMode(self
):
1117 self
._Single
_ = False
1118 if self
._Level
_ > 1:
1119 for Key
in self
.data
:
1120 self
.data
[Key
].SetGreedyMode()
1122 def SetSingleMode(self
):
1123 self
._Single
_ = True
1124 if self
._Level
_ > 1:
1125 for Key
in self
.data
:
1126 self
.data
[Key
].SetSingleMode()
1128 ## Boolean chain list
1130 class Blist(UserList
):
1131 def __init__(self
, initlist
=None):
1132 UserList
.__init
__(self
, initlist
)
1133 def __setitem__(self
, i
, item
):
1134 if item
not in [True, False]:
1140 def _GetResult(self
):
1142 for item
in self
.data
:
1145 Result
= property(_GetResult
)
1147 def ParseConsoleLog(Filename
):
1148 Opr
= open(os
.path
.normpath(Filename
), 'r')
1149 Opw
= open(os
.path
.normpath(Filename
+ '.New'), 'w+')
1150 for Line
in Opr
.readlines():
1151 if Line
.find('.efi') > -1:
1152 Line
= Line
[Line
.rfind(' ') : Line
.rfind('.efi')].strip()
1153 Opw
.write('%s\n' % Line
)
1158 ## check format of PCD value against its the datum type
1160 # For PCD value setting
1162 def CheckPcdDatum(Type
, Value
):
1164 if not ((Value
.startswith('L"') or Value
.startswith('"') and Value
.endswith('"'))
1165 or (Value
.startswith('{') and Value
.endswith('}'))
1167 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1168 ", or \"...\" for string, or L\"...\" for unicode string" % (Value
, Type
)
1169 elif Type
== 'BOOLEAN':
1170 if Value
not in ['TRUE', 'FALSE']:
1171 return False, "Invalid value [%s] of type [%s]; must be TRUE or FALSE" % (Value
, Type
)
1172 elif type(Value
) == type(""):
1174 Value
= long(Value
, 0)
1176 return False, "Invalid value [%s] of type [%s];"\
1177 " must be a hexadecimal, decimal or octal in C language format."\
1182 ## Split command line option string to list
1184 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1185 # in non-windows platform to launch command
1187 def SplitOption(OptionString
):
1192 for Index
in range(0, len(OptionString
)):
1193 CurrentChar
= OptionString
[Index
]
1194 if CurrentChar
in ['"', "'"]:
1195 if QuotationMark
== CurrentChar
:
1197 elif QuotationMark
== "":
1198 QuotationMark
= CurrentChar
1203 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
1204 if Index
> OptionStart
:
1205 OptionList
.append(OptionString
[OptionStart
:Index
-1])
1207 LastChar
= CurrentChar
1208 OptionList
.append(OptionString
[OptionStart
:])
1211 def CommonPath(PathList
):
1212 P1
= min(PathList
).split(os
.path
.sep
)
1213 P2
= max(PathList
).split(os
.path
.sep
)
1214 for Index
in xrange(min(len(P1
), len(P2
))):
1215 if P1
[Index
] != P2
[Index
]:
1216 return os
.path
.sep
.join(P1
[:Index
])
1217 return os
.path
.sep
.join(P1
)
1219 class PathClass(object):
1220 def __init__(self
, File
='', Root
='', AlterRoot
='', Type
='', IsBinary
=False,
1221 Arch
='COMMON', ToolChainFamily
='', Target
='', TagName
='', ToolCode
=''):
1223 self
.File
= str(File
)
1224 if os
.path
.isabs(self
.File
):
1228 self
.Root
= str(Root
)
1229 self
.AlterRoot
= str(AlterRoot
)
1231 # Remove any '.' and '..' in path
1233 self
.Path
= os
.path
.normpath(os
.path
.join(self
.Root
, self
.File
))
1234 self
.Root
= os
.path
.normpath(CommonPath([self
.Root
, self
.Path
]))
1235 # eliminate the side-effect of 'C:'
1236 if self
.Root
[-1] == ':':
1237 self
.Root
+= os
.path
.sep
1238 # file path should not start with path separator
1239 if self
.Root
[-1] == os
.path
.sep
:
1240 self
.File
= self
.Path
[len(self
.Root
):]
1242 self
.File
= self
.Path
[len(self
.Root
)+1:]
1244 self
.Path
= os
.path
.normpath(self
.File
)
1246 self
.SubDir
, self
.Name
= os
.path
.split(self
.File
)
1247 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1251 self
.Dir
= os
.path
.join(self
.Root
, self
.SubDir
)
1253 self
.Dir
= self
.Root
1255 self
.Dir
= self
.SubDir
1260 self
.Type
= self
.Ext
.lower()
1262 self
.IsBinary
= IsBinary
1263 self
.Target
= Target
1264 self
.TagName
= TagName
1265 self
.ToolCode
= ToolCode
1266 self
.ToolChainFamily
= ToolChainFamily
1270 ## Convert the object of this class to a string
1272 # Convert member Path of the class to a string
1274 # @retval string Formatted String
1279 ## Override __eq__ function
1281 # Check whether PathClass are the same
1283 # @retval False The two PathClass are different
1284 # @retval True The two PathClass are the same
1286 def __eq__(self
, Other
):
1287 if type(Other
) == type(self
):
1288 return self
.Path
== Other
.Path
1290 return self
.Path
== str(Other
)
1292 ## Override __hash__ function
1294 # Use Path as key in hash table
1296 # @retval string Key for hash table
1299 return hash(self
.Path
)
1301 def _GetFileKey(self
):
1302 if self
._Key
== None:
1303 self
._Key
= self
.Path
.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1306 def Validate(self
, Type
='', CaseSensitive
=True):
1307 if GlobalData
.gCaseInsensitive
:
1308 CaseSensitive
= False
1309 if Type
and Type
.lower() != self
.Type
:
1310 return FILE_TYPE_MISMATCH
, '%s (expect %s but got %s)' % (self
.File
, Type
, self
.Type
)
1312 RealFile
, RealRoot
= RealPath2(self
.File
, self
.Root
, self
.AlterRoot
)
1313 if not RealRoot
and not RealFile
:
1314 return FILE_NOT_FOUND
, self
.File
1318 if RealRoot
!= self
.Root
or RealFile
!= self
.File
:
1319 if CaseSensitive
and (RealFile
!= self
.File
or (RealRoot
!= self
.Root
and RealRoot
!= self
.AlterRoot
)):
1320 ErrorCode
= FILE_CASE_MISMATCH
1321 ErrorInfo
= self
.File
+ '\n\t' + RealFile
+ " [in file system]"
1323 self
.SubDir
, self
.Name
= os
.path
.split(RealFile
)
1324 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1326 self
.Dir
= os
.path
.join(RealRoot
, self
.SubDir
)
1329 self
.File
= RealFile
1330 self
.Root
= RealRoot
1331 self
.Path
= os
.path
.join(RealRoot
, RealFile
)
1332 return ErrorCode
, ErrorInfo
1334 Key
= property(_GetFileKey
)
1338 # This acts like the main() function for the script, unless it is 'import'ed into another
1341 if __name__
== '__main__':