]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/Misc.py
d6a796bd2b1ec46cab2807205d92035c0064f3a7
2 # Common routines used by all tools
4 # Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
5 # 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.
26 from UserDict
import IterableUserDict
27 from UserList
import UserList
29 from Common
import EdkLogger
as EdkLogger
30 from Common
import GlobalData
as GlobalData
31 from DataType
import *
32 from BuildToolError
import *
34 ## Regular expression used to find out place holders in string template
35 gPlaceholderPattern
= re
.compile("\$\{([^$()\s]+)\}", re
.MULTILINE|re
.UNICODE
)
37 ## Dictionary used to store file time stamp for quick re-access
38 gFileTimeStampCache
= {} # {file path : file time stamp}
40 ## Dictionary used to store dependencies of files
41 gDependencyDatabase
= {} # arch : {file path : [dependent files list]}
43 ## callback routine for processing variable option
45 # This function can be used to process variable number of option values. The
46 # typical usage of it is specify architecure list on command line.
47 # (e.g. <tool> -a IA32 X64 IPF)
49 # @param Option Standard callback function parameter
50 # @param OptionString Standard callback function parameter
51 # @param Value Standard callback function parameter
52 # @param Parser Standard callback function parameter
56 def ProcessVariableArgument(Option
, OptionString
, Value
, Parser
):
59 RawArgs
= Parser
.rargs
62 if (Arg
[:2] == "--" and len(Arg
) > 2) or \
63 (Arg
[:1] == "-" and len(Arg
) > 1 and Arg
[1] != "-"):
67 setattr(Parser
.values
, Option
.dest
, Value
)
69 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
71 # @param Guid The GUID string
73 # @retval string The GUID string in C structure style
75 def GuidStringToGuidStructureString(Guid
):
76 GuidList
= Guid
.split('-')
78 for Index
in range(0,3,1):
79 Result
= Result
+ '0x' + GuidList
[Index
] + ', '
80 Result
= Result
+ '{0x' + GuidList
[3][0:2] + ', 0x' + GuidList
[3][2:4]
81 for Index
in range(0,12,2):
82 Result
= Result
+ ', 0x' + GuidList
[4][Index
:Index
+2]
86 ## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
88 # @param GuidValue The GUID value in byte array
90 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
92 def GuidStructureByteArrayToGuidString(GuidValue
):
93 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
94 guidValueList
= guidValueString
.split(",")
95 if len(guidValueList
) != 16:
97 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
99 return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
100 int(guidValueList
[3], 16),
101 int(guidValueList
[2], 16),
102 int(guidValueList
[1], 16),
103 int(guidValueList
[0], 16),
104 int(guidValueList
[5], 16),
105 int(guidValueList
[4], 16),
106 int(guidValueList
[7], 16),
107 int(guidValueList
[6], 16),
108 int(guidValueList
[8], 16),
109 int(guidValueList
[9], 16),
110 int(guidValueList
[10], 16),
111 int(guidValueList
[11], 16),
112 int(guidValueList
[12], 16),
113 int(guidValueList
[13], 16),
114 int(guidValueList
[14], 16),
115 int(guidValueList
[15], 16)
120 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
122 # @param GuidValue The GUID value in C structure format
124 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
126 def GuidStructureStringToGuidString(GuidValue
):
127 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
128 guidValueList
= guidValueString
.split(",")
129 if len(guidValueList
) != 11:
131 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
133 return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
134 int(guidValueList
[0], 16),
135 int(guidValueList
[1], 16),
136 int(guidValueList
[2], 16),
137 int(guidValueList
[3], 16),
138 int(guidValueList
[4], 16),
139 int(guidValueList
[5], 16),
140 int(guidValueList
[6], 16),
141 int(guidValueList
[7], 16),
142 int(guidValueList
[8], 16),
143 int(guidValueList
[9], 16),
144 int(guidValueList
[10], 16)
149 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
151 # @param GuidValue The GUID value in C structure format
153 # @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
155 def GuidStructureStringToGuidValueName(GuidValue
):
156 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "")
157 guidValueList
= guidValueString
.split(",")
158 if len(guidValueList
) != 11:
159 EdkLogger
.error(None, None, "Invalid GUID value string %s" % GuidValue
)
160 return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (
161 int(guidValueList
[0], 16),
162 int(guidValueList
[1], 16),
163 int(guidValueList
[2], 16),
164 int(guidValueList
[3], 16),
165 int(guidValueList
[4], 16),
166 int(guidValueList
[5], 16),
167 int(guidValueList
[6], 16),
168 int(guidValueList
[7], 16),
169 int(guidValueList
[8], 16),
170 int(guidValueList
[9], 16),
171 int(guidValueList
[10], 16)
174 ## Create directories
176 # @param Directory The directory name
178 def CreateDirectory(Directory
):
179 if Directory
== None or Directory
.strip() == "":
182 if not os
.access(Directory
, os
.F_OK
):
183 os
.makedirs(Directory
)
188 ## Remove directories, including files and sub-directories in it
190 # @param Directory The directory name
192 def RemoveDirectory(Directory
, Recursively
=False):
193 if Directory
== None or Directory
.strip() == "" or not os
.path
.exists(Directory
):
196 CurrentDirectory
= os
.getcwd()
198 for File
in os
.listdir("."):
199 if os
.path
.isdir(File
):
200 RemoveDirectory(File
, Recursively
)
203 os
.chdir(CurrentDirectory
)
206 ## Check if given file is changed or not
208 # This method is used to check if a file is changed or not between two build
209 # actions. It makes use a cache to store files timestamp.
211 # @param File The path of file
213 # @retval True If the given file is changed, doesn't exist, or can't be
214 # found in timestamp cache
215 # @retval False If the given file is changed
218 if not os
.path
.exists(File
):
221 FileState
= os
.stat(File
)
222 TimeStamp
= FileState
[-2]
224 if File
in gFileTimeStampCache
and TimeStamp
== gFileTimeStampCache
[File
]:
228 gFileTimeStampCache
[File
] = TimeStamp
232 ## Store content in file
234 # This method is used to save file only when its content is changed. This is
235 # quite useful for "make" system to decide what will be re-built and what won't.
237 # @param File The path of file
238 # @param Content The new content of the file
239 # @param IsBinaryFile The flag indicating if the file is binary file or not
241 # @retval True If the file content is changed and the file is renewed
242 # @retval False If the file content is the same
244 def SaveFileOnChange(File
, Content
, IsBinaryFile
=True):
246 Content
= Content
.replace("\n", os
.linesep
)
248 if os
.path
.exists(File
):
250 if Content
== open(File
, "rb").read():
253 EdkLogger
.error(None, FILE_OPEN_FAILURE
, ExtraData
=File
)
255 DirName
= os
.path
.dirname(File
)
256 if not CreateDirectory(DirName
):
257 EdkLogger
.error(None, FILE_CREATE_FAILURE
, "Could not create directory %s" % DirName
)
260 DirName
= os
.getcwd()
261 if not os
.access(DirName
, os
.W_OK
):
262 EdkLogger
.error(None, PERMISSION_FAILURE
, "Do not have write permission on directory %s" % DirName
)
265 if GlobalData
.gIsWindows
:
267 from PyUtility
import SaveFileToDisk
268 if not SaveFileToDisk(File
, Content
):
269 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
=File
)
271 Fd
= open(File
, "wb")
275 Fd
= open(File
, "wb")
279 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
='IOError %s'%X)
283 ## Make a Python object persistent on file system
285 # @param Data The object to be stored in file
286 # @param File The path of file to store the object
288 def DataDump(Data
, File
):
291 Fd
= open(File
, 'wb')
292 cPickle
.dump(Data
, Fd
, cPickle
.HIGHEST_PROTOCOL
)
294 EdkLogger
.error("", FILE_OPEN_FAILURE
, ExtraData
=File
, RaiseError
=False)
299 ## Restore a Python object from a file
301 # @param File The path of file stored the object
303 # @retval object A python object
304 # @retval None If failure in file operation
306 def DataRestore(File
):
310 Fd
= open(File
, 'rb')
311 Data
= cPickle
.load(Fd
)
313 EdkLogger
.verbose("Failed to load [%s]\n\t%s" % (File
, str(e
)))
320 ## Retrieve and cache the real path name in file system
322 # @param Root The root directory of path relative to
324 # @retval str The path string if the path exists
325 # @retval None If path doesn't exist
331 def __init__(self
, Root
):
333 for F
in os
.listdir(Root
):
335 self
._UPPER
_CACHE
_[F
.upper()] = F
338 def __getitem__(self
, Path
):
339 Path
= Path
[len(os
.path
.commonprefix([Path
, self
._Root
])):]
342 if Path
and Path
[0] == os
.path
.sep
:
344 if Path
in self
._CACHE
_:
345 return os
.path
.join(self
._Root
, Path
)
346 UpperPath
= Path
.upper()
347 if UpperPath
in self
._UPPER
_CACHE
_:
348 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
352 SepIndex
= Path
.find(os
.path
.sep
)
354 Parent
= UpperPath
[:SepIndex
]
355 if Parent
not in self
._UPPER
_CACHE
_:
357 LastSepIndex
= SepIndex
358 SepIndex
= Path
.find(os
.path
.sep
, LastSepIndex
+ 1)
360 if LastSepIndex
== -1:
365 SepIndex
= LastSepIndex
367 Parent
= Path
[:SepIndex
]
368 ParentKey
= UpperPath
[:SepIndex
]
369 if ParentKey
not in self
._UPPER
_CACHE
_:
373 if Parent
in self
._CACHE
_:
376 ParentDir
= self
._UPPER
_CACHE
_[ParentKey
]
377 for F
in os
.listdir(ParentDir
):
378 Dir
= os
.path
.join(ParentDir
, F
)
379 self
._CACHE
_.add(Dir
)
380 self
._UPPER
_CACHE
_[Dir
.upper()] = Dir
382 SepIndex
= Path
.find(os
.path
.sep
, SepIndex
+ 1)
385 if Path
in self
._CACHE
_:
386 return os
.path
.join(self
._Root
, Path
)
387 elif UpperPath
in self
._UPPER
_CACHE
_:
388 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
391 ## Get all files of a directory
393 # @param Root: Root dir
394 # @param SkipList : The files need be skipped
396 # @retval A list of all files
398 def GetFiles(Root
, SkipList
=None, FullPath
= True):
401 for Root
, Dirs
, Files
in os
.walk(Root
):
403 for Item
in SkipList
:
408 File
= os
.path
.normpath(os
.path
.join(Root
, File
))
410 File
= File
[len(OriPath
) + 1:]
411 FileList
.append(File
)
415 ## Check if gvien file exists or not
417 # @param File File name or path to be checked
418 # @param Dir The directory the file is relative to
420 # @retval True if file exists
421 # @retval False if file doesn't exists
423 def ValidFile(File
, Ext
=None):
425 Dummy
, FileExt
= os
.path
.splitext(File
)
426 if FileExt
.lower() != Ext
.lower():
428 if not os
.path
.exists(File
):
432 def RealPath(File
, Dir
='', OverrideDir
=''):
433 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
434 NewFile
= GlobalData
.gAllFiles
[NewFile
]
435 if not NewFile
and OverrideDir
:
436 NewFile
= os
.path
.normpath(os
.path
.join(OverrideDir
, File
))
437 NewFile
= GlobalData
.gAllFiles
[NewFile
]
440 def RealPath2(File
, Dir
='', OverrideDir
=''):
442 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
444 if OverrideDir
[-1] == os
.path
.sep
:
445 return NewFile
[len(OverrideDir
):], NewFile
[0:len(OverrideDir
)]
447 return NewFile
[len(OverrideDir
)+1:], NewFile
[0:len(OverrideDir
)]
449 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
452 if Dir
[-1] == os
.path
.sep
:
453 return NewFile
[len(Dir
):], NewFile
[0:len(Dir
)]
455 return NewFile
[len(Dir
)+1:], NewFile
[0:len(Dir
)]
461 ## Check if gvien file exists or not
464 def ValidFile2(AllFiles
, File
, Ext
=None, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
467 Dummy
, FileExt
= os
.path
.splitext(File
)
468 if FileExt
.lower() != Ext
.lower():
471 # Replace the Edk macros
472 if OverrideDir
!= '' and OverrideDir
!= None:
473 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
474 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
475 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
476 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
478 # Replace the default dir to current dir
481 Dir
= Dir
[len(Workspace
)+1:]
483 # First check if File has Edk definition itself
484 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
485 NewFile
= File
.replace('$(EFI_SOURCE)', EfiSource
)
486 NewFile
= NewFile
.replace('$(EDK_SOURCE)', EdkSource
)
487 NewFile
= AllFiles
[os
.path
.normpath(NewFile
)]
491 # Second check the path with override value
492 if OverrideDir
!= '' and OverrideDir
!= None:
493 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
497 # Last check the path with normal definitions
498 File
= os
.path
.join(Dir
, File
)
499 NewFile
= AllFiles
[os
.path
.normpath(File
)]
505 ## Check if gvien file exists or not
508 def ValidFile3(AllFiles
, File
, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
509 # Replace the Edk macros
510 if OverrideDir
!= '' and OverrideDir
!= None:
511 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
512 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
513 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
514 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
516 # Replace the default dir to current dir
517 # Dir is current module dir related to workspace
520 Dir
= Dir
[len(Workspace
)+1:]
523 RelaPath
= AllFiles
[os
.path
.normpath(Dir
)]
524 NewRelaPath
= RelaPath
527 # First check if File has Edk definition itself
528 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
529 File
= File
.replace('$(EFI_SOURCE)', EfiSource
)
530 File
= File
.replace('$(EDK_SOURCE)', EdkSource
)
531 NewFile
= AllFiles
[os
.path
.normpath(File
)]
533 NewRelaPath
= os
.path
.dirname(NewFile
)
534 File
= os
.path
.basename(NewFile
)
535 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
538 # Second check the path with override value
539 if OverrideDir
!= '' and OverrideDir
!= None:
540 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
542 #NewRelaPath = os.path.dirname(NewFile)
543 NewRelaPath
= NewFile
[:len(NewFile
) - len(File
.replace("..\\", '').replace("../", '')) - 1]
546 # Last check the path with normal definitions
547 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
554 return NewRelaPath
, RelaPath
, File
557 def GetRelPath(Path1
, Path2
):
558 FileName
= os
.path
.basename(Path2
)
559 L1
= os
.path
.normpath(Path1
).split(os
.path
.normpath('/'))
560 L2
= os
.path
.normpath(Path2
).split(os
.path
.normpath('/'))
561 for Index
in range(0, len(L1
)):
562 if L1
[Index
] != L2
[Index
]:
563 FileName
= '../' * (len(L1
) - Index
)
564 for Index2
in range(Index
, len(L2
)):
565 FileName
= os
.path
.join(FileName
, L2
[Index2
])
567 return os
.path
.normpath(FileName
)
570 ## Get GUID value from given packages
572 # @param CName The CName of the GUID
573 # @param PackageList List of packages looking-up in
575 # @retval GuidValue if the CName is found in any given package
576 # @retval None if the CName is not found in all given packages
578 def GuidValue(CName
, PackageList
):
579 for P
in PackageList
:
581 return P
.Guids
[CName
]
584 ## Get Protocol value from given packages
586 # @param CName The CName of the GUID
587 # @param PackageList List of packages looking-up in
589 # @retval GuidValue if the CName is found in any given package
590 # @retval None if the CName is not found in all given packages
592 def ProtocolValue(CName
, PackageList
):
593 for P
in PackageList
:
594 if CName
in P
.Protocols
:
595 return P
.Protocols
[CName
]
598 ## Get PPI value from given packages
600 # @param CName The CName of the GUID
601 # @param PackageList List of packages looking-up in
603 # @retval GuidValue if the CName is found in any given package
604 # @retval None if the CName is not found in all given packages
606 def PpiValue(CName
, PackageList
):
607 for P
in PackageList
:
612 ## A string template class
614 # This class implements a template for string replacement. A string template
615 # looks like following
617 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
619 # The string between ${BEGIN} and ${END} will be repeated as many times as the
620 # length of "placeholder_name", which is a list passed through a dict. The
621 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
622 # be not used and, in this case, the "placeholder_name" must not a list and it
623 # will just be replaced once.
625 class TemplateString(object):
626 _REPEAT_START_FLAG
= "BEGIN"
627 _REPEAT_END_FLAG
= "END"
629 class Section(object):
630 _LIST_TYPES
= [type([]), type(set()), type((0,))]
632 def __init__(self
, TemplateSection
, PlaceHolderList
):
633 self
._Template
= TemplateSection
634 self
._PlaceHolderList
= []
636 # Split the section into sub-sections according to the position of placeholders
638 self
._SubSectionList
= []
641 # The placeholders passed in must be in the format of
643 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
645 for PlaceHolder
,Start
,End
in PlaceHolderList
:
646 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:Start
])
647 self
._SubSectionList
.append(TemplateSection
[Start
:End
])
648 self
._PlaceHolderList
.append(PlaceHolder
)
649 SubSectionStart
= End
650 if SubSectionStart
< len(TemplateSection
):
651 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:])
653 self
._SubSectionList
= [TemplateSection
]
656 return self
._Template
+ " : " + str(self
._PlaceHolderList
)
658 def Instantiate(self
, PlaceHolderValues
):
660 RepeatPlaceHolders
= {}
661 NonRepeatPlaceHolders
= {}
663 for PlaceHolder
in self
._PlaceHolderList
:
664 if PlaceHolder
not in PlaceHolderValues
:
666 Value
= PlaceHolderValues
[PlaceHolder
]
667 if type(Value
) in self
._LIST
_TYPES
:
669 RepeatTime
= len(Value
)
670 elif RepeatTime
!= len(Value
):
674 "${%s} has different repeat time from others!" % PlaceHolder
,
675 ExtraData
=str(self
._Template
)
677 RepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
679 NonRepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
681 if NonRepeatPlaceHolders
:
683 for S
in self
._SubSectionList
:
684 if S
not in NonRepeatPlaceHolders
:
687 StringList
.append(str(NonRepeatPlaceHolders
[S
]))
689 StringList
= self
._SubSectionList
691 if RepeatPlaceHolders
:
693 for Index
in range(RepeatTime
):
695 if S
not in RepeatPlaceHolders
:
696 TempStringList
.append(S
)
698 TempStringList
.append(str(RepeatPlaceHolders
[S
][Index
]))
699 StringList
= TempStringList
701 return "".join(StringList
)
704 def __init__(self
, Template
=None):
706 self
.IsBinary
= False
707 self
._Template
= Template
708 self
._TemplateSectionList
= self
._Parse
(Template
)
712 # @retval string The string replaced
717 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
719 # @retval list A list of TemplateString.Section objects
721 def _Parse(self
, Template
):
726 TemplateSectionList
= []
728 MatchObj
= gPlaceholderPattern
.search(Template
, SearchFrom
)
730 if MatchEnd
<= len(Template
):
731 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:], PlaceHolderList
)
732 TemplateSectionList
.append(TemplateSection
)
735 MatchString
= MatchObj
.group(1)
736 MatchStart
= MatchObj
.start()
737 MatchEnd
= MatchObj
.end()
739 if MatchString
== self
._REPEAT
_START
_FLAG
:
740 if MatchStart
> SectionStart
:
741 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
742 TemplateSectionList
.append(TemplateSection
)
743 SectionStart
= MatchEnd
745 elif MatchString
== self
._REPEAT
_END
_FLAG
:
746 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
747 TemplateSectionList
.append(TemplateSection
)
748 SectionStart
= MatchEnd
751 PlaceHolderList
.append((MatchString
, MatchStart
- SectionStart
, MatchEnd
- SectionStart
))
752 SearchFrom
= MatchEnd
753 return TemplateSectionList
755 ## Replace the string template with dictionary of placeholders and append it to previous one
757 # @param AppendString The string template to append
758 # @param Dictionary The placeholder dictionaries
760 def Append(self
, AppendString
, Dictionary
=None):
762 SectionList
= self
._Parse
(AppendString
)
763 self
.String
+= "".join([S
.Instantiate(Dictionary
) for S
in SectionList
])
765 self
.String
+= AppendString
767 ## Replace the string template with dictionary of placeholders
769 # @param Dictionary The placeholder dictionaries
771 # @retval str The string replaced with placeholder values
773 def Replace(self
, Dictionary
=None):
774 return "".join([S
.Instantiate(Dictionary
) for S
in self
._TemplateSectionList
])
776 ## Progress indicator class
778 # This class makes use of thread to print progress on console.
781 # for avoiding deadloop
783 _ProgressThread
= None
784 _CheckInterval
= 0.25
788 # @param OpenMessage The string printed before progress charaters
789 # @param CloseMessage The string printed after progress charaters
790 # @param ProgressChar The charater used to indicate the progress
791 # @param Interval The interval in seconds between two progress charaters
793 def __init__(self
, OpenMessage
="", CloseMessage
="", ProgressChar
='.', Interval
=1.0):
794 self
.PromptMessage
= OpenMessage
795 self
.CodaMessage
= CloseMessage
796 self
.ProgressChar
= ProgressChar
797 self
.Interval
= Interval
798 if Progressor
._StopFlag
== None:
799 Progressor
._StopFlag
= threading
.Event()
801 ## Start to print progress charater
803 # @param OpenMessage The string printed before progress charaters
805 def Start(self
, OpenMessage
=None):
806 if OpenMessage
!= None:
807 self
.PromptMessage
= OpenMessage
808 Progressor
._StopFlag
.clear()
809 if Progressor
._ProgressThread
== None:
810 Progressor
._ProgressThread
= threading
.Thread(target
=self
._ProgressThreadEntry
)
811 Progressor
._ProgressThread
.setDaemon(False)
812 Progressor
._ProgressThread
.start()
814 ## Stop printing progress charater
816 # @param CloseMessage The string printed after progress charaters
818 def Stop(self
, CloseMessage
=None):
819 OriginalCodaMessage
= self
.CodaMessage
820 if CloseMessage
!= None:
821 self
.CodaMessage
= CloseMessage
823 self
.CodaMessage
= OriginalCodaMessage
825 ## Thread entry method
826 def _ProgressThreadEntry(self
):
827 sys
.stdout
.write(self
.PromptMessage
+ " ")
830 while not Progressor
._StopFlag
.isSet():
832 sys
.stdout
.write(self
.ProgressChar
)
834 TimeUp
= self
.Interval
835 time
.sleep(self
._CheckInterval
)
836 TimeUp
-= self
._CheckInterval
837 sys
.stdout
.write(" " + self
.CodaMessage
+ "\n")
840 ## Abort the progress display
843 if Progressor
._StopFlag
!= None:
844 Progressor
._StopFlag
.set()
845 if Progressor
._ProgressThread
!= None:
846 Progressor
._ProgressThread
.join()
847 Progressor
._ProgressThread
= None
849 ## A dict which can access its keys and/or values orderly
851 # The class implements a new kind of dict which its keys or values can be
852 # accessed in the order they are added into the dict. It guarantees the order
853 # by making use of an internal list to keep a copy of keys.
855 class sdict(IterableUserDict
):
858 IterableUserDict
.__init
__(self
)
862 def __setitem__(self
, key
, value
):
863 if key
not in self
._key
_list
:
864 self
._key
_list
.append(key
)
865 IterableUserDict
.__setitem
__(self
, key
, value
)
868 def __delitem__(self
, key
):
869 self
._key
_list
.remove(key
)
870 IterableUserDict
.__delitem
__(self
, key
)
872 ## used in "for k in dict" loop to ensure the correct order
874 return self
.iterkeys()
878 return len(self
._key
_list
)
881 def __contains__(self
, key
):
882 return key
in self
._key
_list
885 def index(self
, key
):
886 return self
._key
_list
.index(key
)
889 def insert(self
, key
, newkey
, newvalue
, order
):
890 index
= self
._key
_list
.index(key
)
891 if order
== 'BEFORE':
892 self
._key
_list
.insert(index
, newkey
)
893 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
894 elif order
== 'AFTER':
895 self
._key
_list
.insert(index
+ 1, newkey
)
896 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
899 def append(self
, sdict
):
901 if key
not in self
._key
_list
:
902 self
._key
_list
.append(key
)
903 IterableUserDict
.__setitem
__(self
, key
, sdict
[key
])
905 def has_key(self
, key
):
906 return key
in self
._key
_list
911 IterableUserDict
.clear(self
)
913 ## Return a copy of keys
916 for key
in self
._key
_list
:
920 ## Return a copy of values
923 for key
in self
._key
_list
:
924 values
.append(self
[key
])
927 ## Return a copy of (key, value) list
930 for key
in self
._key
_list
:
931 items
.append((key
, self
[key
]))
936 return iter(self
.items())
938 ## Keys interation support
940 return iter(self
.keys())
942 ## Values interation support
943 def itervalues(self
):
944 return iter(self
.values())
946 ## Return value related to a key, and remove the (key, value) from the dict
947 def pop(self
, key
, *dv
):
949 if key
in self
._key
_list
:
951 self
.__delitem
__(key
)
956 ## Return (key, value) pair, and remove the (key, value) from the dict
958 key
= self
._key
_list
[-1]
960 self
.__delitem
__(key
)
963 def update(self
, dict=None, **kwargs
):
965 for k
, v
in dict.items():
968 for k
, v
in kwargs
.items():
971 ## Dictionary with restricted keys
975 def __init__(self
, KeyList
):
977 dict.__setitem
__(self
, Key
, "")
980 def __setitem__(self
, key
, value
):
982 EdkLogger
.error("RestrictedDict", ATTRIBUTE_SET_FAILURE
, "Key [%s] is not allowed" % key
,
983 ExtraData
=", ".join(dict.keys(self
)))
984 dict.__setitem
__(self
, key
, value
)
987 def __getitem__(self
, key
):
990 return dict.__getitem
__(self
, key
)
993 def __delitem__(self
, key
):
994 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="del")
999 self
.__setitem
__(Key
, "")
1001 ## Return value related to a key, and remove the (key, value) from the dict
1002 def pop(self
, key
, *dv
):
1003 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="pop")
1005 ## Return (key, value) pair, and remove the (key, value) from the dict
1007 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="popitem")
1009 ## Dictionary using prioritized list as key
1012 _ListType
= type([])
1013 _TupleType
= type(())
1014 _Wildcard
= 'COMMON'
1015 _ValidWildcardList
= ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1017 def __init__(self
, _Single_
=False, _Level_
=2):
1018 self
._Level
_ = _Level_
1020 self
._Single
_ = _Single_
1023 def __getitem__(self
, key
):
1026 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1030 elif self
._Level
_ > 1:
1031 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1034 if self
._Level
_ > 1:
1035 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1037 if FirstKey
== None or str(FirstKey
).upper() in self
._ValidWildcardList
:
1038 FirstKey
= self
._Wildcard
1041 return self
._GetSingleValue
(FirstKey
, RestKeys
)
1043 return self
._GetAllValues
(FirstKey
, RestKeys
)
1045 def _GetSingleValue(self
, FirstKey
, RestKeys
):
1047 #print "%s-%s" % (FirstKey, self._Level_) ,
1048 if self
._Level
_ > 1:
1049 if FirstKey
== self
._Wildcard
:
1050 if FirstKey
in self
.data
:
1051 Value
= self
.data
[FirstKey
][RestKeys
]
1053 for Key
in self
.data
:
1054 Value
= self
.data
[Key
][RestKeys
]
1055 if Value
!= None: break
1057 if FirstKey
in self
.data
:
1058 Value
= self
.data
[FirstKey
][RestKeys
]
1059 if Value
== None and self
._Wildcard
in self
.data
:
1061 Value
= self
.data
[self
._Wildcard
][RestKeys
]
1063 if FirstKey
== self
._Wildcard
:
1064 if FirstKey
in self
.data
:
1065 Value
= self
.data
[FirstKey
]
1067 for Key
in self
.data
:
1068 Value
= self
.data
[Key
]
1069 if Value
!= None: break
1071 if FirstKey
in self
.data
:
1072 Value
= self
.data
[FirstKey
]
1073 elif self
._Wildcard
in self
.data
:
1074 Value
= self
.data
[self
._Wildcard
]
1077 def _GetAllValues(self
, FirstKey
, RestKeys
):
1079 if self
._Level
_ > 1:
1080 if FirstKey
== self
._Wildcard
:
1081 for Key
in self
.data
:
1082 Value
+= self
.data
[Key
][RestKeys
]
1084 if FirstKey
in self
.data
:
1085 Value
+= self
.data
[FirstKey
][RestKeys
]
1086 if self
._Wildcard
in self
.data
:
1087 Value
+= self
.data
[self
._Wildcard
][RestKeys
]
1089 if FirstKey
== self
._Wildcard
:
1090 for Key
in self
.data
:
1091 Value
.append(self
.data
[Key
])
1093 if FirstKey
in self
.data
:
1094 Value
.append(self
.data
[FirstKey
])
1095 if self
._Wildcard
in self
.data
:
1096 Value
.append(self
.data
[self
._Wildcard
])
1100 def __setitem__(self
, key
, value
):
1103 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1108 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1111 if self
._Level
_ > 1:
1112 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1114 if FirstKey
in self
._ValidWildcardList
:
1115 FirstKey
= self
._Wildcard
1117 if FirstKey
not in self
.data
and self
._Level
_ > 0:
1118 self
.data
[FirstKey
] = tdict(self
._Single
_, self
._Level
_ - 1)
1120 if self
._Level
_ > 1:
1121 self
.data
[FirstKey
][RestKeys
] = value
1123 self
.data
[FirstKey
] = value
1125 def SetGreedyMode(self
):
1126 self
._Single
_ = False
1127 if self
._Level
_ > 1:
1128 for Key
in self
.data
:
1129 self
.data
[Key
].SetGreedyMode()
1131 def SetSingleMode(self
):
1132 self
._Single
_ = True
1133 if self
._Level
_ > 1:
1134 for Key
in self
.data
:
1135 self
.data
[Key
].SetSingleMode()
1137 def GetKeys(self
, KeyIndex
=0):
1138 assert KeyIndex
>= 0
1140 return set(self
.data
.keys())
1143 for Key
in self
.data
:
1144 keys |
= self
.data
[Key
].GetKeys(KeyIndex
- 1)
1147 ## Boolean chain list
1149 class Blist(UserList
):
1150 def __init__(self
, initlist
=None):
1151 UserList
.__init
__(self
, initlist
)
1152 def __setitem__(self
, i
, item
):
1153 if item
not in [True, False]:
1159 def _GetResult(self
):
1161 for item
in self
.data
:
1164 Result
= property(_GetResult
)
1166 def ParseConsoleLog(Filename
):
1167 Opr
= open(os
.path
.normpath(Filename
), 'r')
1168 Opw
= open(os
.path
.normpath(Filename
+ '.New'), 'w+')
1169 for Line
in Opr
.readlines():
1170 if Line
.find('.efi') > -1:
1171 Line
= Line
[Line
.rfind(' ') : Line
.rfind('.efi')].strip()
1172 Opw
.write('%s\n' % Line
)
1179 # Analyze the pcd Value, Datum type and TokenNumber.
1180 # Used to avoid split issue while the value string contain "|" character
1182 # @param[in] Setting: A String contain value/datum type/token number information;
1184 # @retval ValueList: A List contain value, datum type and toke number.
1186 def AnalyzePcdData(Setting
):
1187 ValueList
= ['', '', '']
1189 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1190 PtrValue
= ValueRe
.findall(Setting
)
1192 ValueUpdateFlag
= False
1194 if len(PtrValue
) >= 1:
1195 Setting
= re
.sub(ValueRe
, '', Setting
)
1196 ValueUpdateFlag
= True
1198 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1199 ValueList
[0:len(TokenList
)] = TokenList
1202 ValueList
[0] = PtrValue
[0]
1206 ## AnalyzeHiiPcdData
1208 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1209 # Used to avoid split issue while the value string contain "|" character
1211 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1213 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1215 def AnalyzeHiiPcdData(Setting
):
1216 ValueList
= ['', '', '', '']
1218 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1219 PtrValue
= ValueRe
.findall(Setting
)
1221 ValueUpdateFlag
= False
1223 if len(PtrValue
) >= 1:
1224 Setting
= re
.sub(ValueRe
, '', Setting
)
1225 ValueUpdateFlag
= True
1227 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1228 ValueList
[0:len(TokenList
)] = TokenList
1231 ValueList
[0] = PtrValue
[0]
1235 ## AnalyzeVpdPcdData
1237 # Analyze the vpd pcd Value, Datum type and TokenNumber.
1238 # Used to avoid split issue while the value string contain "|" character
1240 # @param[in] Setting: A String contain value/datum type/token number information;
1242 # @retval ValueList: A List contain value, datum type and toke number.
1244 def AnalyzeVpdPcdData(Setting
):
1245 ValueList
= ['', '', '']
1247 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
1248 PtrValue
= ValueRe
.findall(Setting
)
1250 ValueUpdateFlag
= False
1252 if len(PtrValue
) >= 1:
1253 Setting
= re
.sub(ValueRe
, '', Setting
)
1254 ValueUpdateFlag
= True
1256 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1257 ValueList
[0:len(TokenList
)] = TokenList
1260 ValueList
[2] = PtrValue
[0]
1264 ## check format of PCD value against its the datum type
1266 # For PCD value setting
1268 def CheckPcdDatum(Type
, Value
):
1270 if not (((Value
.startswith('L"') or Value
.startswith('"')) and Value
.endswith('"'))
1271 or (Value
.startswith('{') and Value
.endswith('}'))
1273 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1274 ", or \"...\" for string, or L\"...\" for unicode string" % (Value
, Type
)
1275 elif Type
== 'BOOLEAN':
1276 if Value
not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1277 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1278 ", FALSE, False, false, 0x0, 0x00, 0" % (Value
, Type
)
1279 elif type(Value
) == type(""):
1281 Value
= long(Value
, 0)
1283 return False, "Invalid value [%s] of type [%s];"\
1284 " must be a hexadecimal, decimal or octal in C language format."\
1289 ## Split command line option string to list
1291 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1292 # in non-windows platform to launch command
1294 def SplitOption(OptionString
):
1299 for Index
in range(0, len(OptionString
)):
1300 CurrentChar
= OptionString
[Index
]
1301 if CurrentChar
in ['"', "'"]:
1302 if QuotationMark
== CurrentChar
:
1304 elif QuotationMark
== "":
1305 QuotationMark
= CurrentChar
1310 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
1311 if Index
> OptionStart
:
1312 OptionList
.append(OptionString
[OptionStart
:Index
-1])
1314 LastChar
= CurrentChar
1315 OptionList
.append(OptionString
[OptionStart
:])
1318 def CommonPath(PathList
):
1319 P1
= min(PathList
).split(os
.path
.sep
)
1320 P2
= max(PathList
).split(os
.path
.sep
)
1321 for Index
in xrange(min(len(P1
), len(P2
))):
1322 if P1
[Index
] != P2
[Index
]:
1323 return os
.path
.sep
.join(P1
[:Index
])
1324 return os
.path
.sep
.join(P1
)
1326 class PathClass(object):
1327 def __init__(self
, File
='', Root
='', AlterRoot
='', Type
='', IsBinary
=False,
1328 Arch
='COMMON', ToolChainFamily
='', Target
='', TagName
='', ToolCode
=''):
1330 self
.File
= str(File
)
1331 if os
.path
.isabs(self
.File
):
1335 self
.Root
= str(Root
)
1336 self
.AlterRoot
= str(AlterRoot
)
1338 # Remove any '.' and '..' in path
1340 self
.Path
= os
.path
.normpath(os
.path
.join(self
.Root
, self
.File
))
1341 self
.Root
= os
.path
.normpath(CommonPath([self
.Root
, self
.Path
]))
1342 # eliminate the side-effect of 'C:'
1343 if self
.Root
[-1] == ':':
1344 self
.Root
+= os
.path
.sep
1345 # file path should not start with path separator
1346 if self
.Root
[-1] == os
.path
.sep
:
1347 self
.File
= self
.Path
[len(self
.Root
):]
1349 self
.File
= self
.Path
[len(self
.Root
)+1:]
1351 self
.Path
= os
.path
.normpath(self
.File
)
1353 self
.SubDir
, self
.Name
= os
.path
.split(self
.File
)
1354 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1358 self
.Dir
= os
.path
.join(self
.Root
, self
.SubDir
)
1360 self
.Dir
= self
.Root
1362 self
.Dir
= self
.SubDir
1367 self
.Type
= self
.Ext
.lower()
1369 self
.IsBinary
= IsBinary
1370 self
.Target
= Target
1371 self
.TagName
= TagName
1372 self
.ToolCode
= ToolCode
1373 self
.ToolChainFamily
= ToolChainFamily
1377 ## Convert the object of this class to a string
1379 # Convert member Path of the class to a string
1381 # @retval string Formatted String
1386 ## Override __eq__ function
1388 # Check whether PathClass are the same
1390 # @retval False The two PathClass are different
1391 # @retval True The two PathClass are the same
1393 def __eq__(self
, Other
):
1394 if type(Other
) == type(self
):
1395 return self
.Path
== Other
.Path
1397 return self
.Path
== str(Other
)
1399 ## Override __hash__ function
1401 # Use Path as key in hash table
1403 # @retval string Key for hash table
1406 return hash(self
.Path
)
1408 def _GetFileKey(self
):
1409 if self
._Key
== None:
1410 self
._Key
= self
.Path
.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1413 def Validate(self
, Type
='', CaseSensitive
=True):
1414 if GlobalData
.gCaseInsensitive
:
1415 CaseSensitive
= False
1416 if Type
and Type
.lower() != self
.Type
:
1417 return FILE_TYPE_MISMATCH
, '%s (expect %s but got %s)' % (self
.File
, Type
, self
.Type
)
1419 RealFile
, RealRoot
= RealPath2(self
.File
, self
.Root
, self
.AlterRoot
)
1420 if not RealRoot
and not RealFile
:
1421 RealFile
= self
.File
1423 RealFile
= os
.path
.join(self
.AlterRoot
, self
.File
)
1425 RealFile
= os
.path
.join(self
.Root
, self
.File
)
1426 return FILE_NOT_FOUND
, os
.path
.join(self
.AlterRoot
, RealFile
)
1430 if RealRoot
!= self
.Root
or RealFile
!= self
.File
:
1431 if CaseSensitive
and (RealFile
!= self
.File
or (RealRoot
!= self
.Root
and RealRoot
!= self
.AlterRoot
)):
1432 ErrorCode
= FILE_CASE_MISMATCH
1433 ErrorInfo
= self
.File
+ '\n\t' + RealFile
+ " [in file system]"
1435 self
.SubDir
, self
.Name
= os
.path
.split(RealFile
)
1436 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1438 self
.Dir
= os
.path
.join(RealRoot
, self
.SubDir
)
1441 self
.File
= RealFile
1442 self
.Root
= RealRoot
1443 self
.Path
= os
.path
.join(RealRoot
, RealFile
)
1444 return ErrorCode
, ErrorInfo
1446 Key
= property(_GetFileKey
)
1448 ## Parse PE image to get the required PE informaion.
1450 class PeImageClass():
1453 # @param File FilePath of PeImage
1455 def __init__(self
, PeFile
):
1456 self
.FileName
= PeFile
1457 self
.IsValid
= False
1460 self
.SectionAlignment
= 0
1461 self
.SectionHeaderList
= []
1464 PeObject
= open(PeFile
, 'rb')
1466 self
.ErrorInfo
= self
.FileName
+ ' can not be found\n'
1469 ByteArray
= array
.array('B')
1470 ByteArray
.fromfile(PeObject
, 0x3E)
1471 ByteList
= ByteArray
.tolist()
1472 # DOS signature should be 'MZ'
1473 if self
._ByteListToStr
(ByteList
[0x0:0x2]) != 'MZ':
1474 self
.ErrorInfo
= self
.FileName
+ ' has no valid DOS signature MZ'
1477 # Read 4 byte PE Signature
1478 PeOffset
= self
._ByteListToInt
(ByteList
[0x3C:0x3E])
1479 PeObject
.seek(PeOffset
)
1480 ByteArray
= array
.array('B')
1481 ByteArray
.fromfile(PeObject
, 4)
1482 # PE signature should be 'PE\0\0'
1483 if ByteArray
.tostring() != 'PE\0\0':
1484 self
.ErrorInfo
= self
.FileName
+ ' has no valid PE signature PE00'
1487 # Read PE file header
1488 ByteArray
= array
.array('B')
1489 ByteArray
.fromfile(PeObject
, 0x14)
1490 ByteList
= ByteArray
.tolist()
1491 SecNumber
= self
._ByteListToInt
(ByteList
[0x2:0x4])
1493 self
.ErrorInfo
= self
.FileName
+ ' has no section header'
1496 # Read PE optional header
1497 OptionalHeaderSize
= self
._ByteListToInt
(ByteArray
[0x10:0x12])
1498 ByteArray
= array
.array('B')
1499 ByteArray
.fromfile(PeObject
, OptionalHeaderSize
)
1500 ByteList
= ByteArray
.tolist()
1501 self
.EntryPoint
= self
._ByteListToInt
(ByteList
[0x10:0x14])
1502 self
.SectionAlignment
= self
._ByteListToInt
(ByteList
[0x20:0x24])
1503 self
.Size
= self
._ByteListToInt
(ByteList
[0x38:0x3C])
1505 # Read each Section Header
1506 for Index
in range(SecNumber
):
1507 ByteArray
= array
.array('B')
1508 ByteArray
.fromfile(PeObject
, 0x28)
1509 ByteList
= ByteArray
.tolist()
1510 SecName
= self
._ByteListToStr
(ByteList
[0:8])
1511 SecVirtualSize
= self
._ByteListToInt
(ByteList
[8:12])
1512 SecRawAddress
= self
._ByteListToInt
(ByteList
[20:24])
1513 SecVirtualAddress
= self
._ByteListToInt
(ByteList
[12:16])
1514 self
.SectionHeaderList
.append((SecName
, SecVirtualAddress
, SecRawAddress
, SecVirtualSize
))
1518 def _ByteListToStr(self
, ByteList
):
1520 for index
in range(len(ByteList
)):
1521 if ByteList
[index
] == 0:
1523 String
+= chr(ByteList
[index
])
1526 def _ByteListToInt(self
, ByteList
):
1528 for index
in range(len(ByteList
) - 1, -1, -1):
1529 Value
= (Value
<< 8) |
int(ByteList
[index
])
1534 # This acts like the main() function for the script, unless it is 'import'ed into another
1537 if __name__
== '__main__':