2 # Contains several utilitities shared by migration tools.
4 # Copyright (c) 2007 - 2014, 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.
17 import Common
.LongFilePathOs
as os
20 from optparse
import OptionParser
21 from Common
.BuildToolError
import *
22 from XmlRoutines
import *
23 from CommonDataClass
.CommonClass
import *
24 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
26 ## Set all fields of CommonClass object.
28 # Set all attributes of CommonClass object from XML Dom object of XmlCommon.
30 # @param Common The destine CommonClass object.
31 # @param XmlCommon The source XML Dom object.
33 def SetCommon(Common
, XmlCommon
):
35 Common
.Usage
= XmlAttribute(XmlCommon
, XmlTag
).split()
37 XmlTag
= "FeatureFlag"
38 Common
.FeatureFlag
= XmlAttribute(XmlCommon
, XmlTag
)
40 XmlTag
= "SupArchList"
41 Common
.SupArchList
= XmlAttribute(XmlCommon
, XmlTag
).split()
43 XmlTag
= XmlNodeName(XmlCommon
) + "/" + "HelpText"
44 Common
.HelpText
= XmlElement(XmlCommon
, XmlTag
)
47 ## Set some fields of CommonHeaderClass object.
49 # Set Name, Guid, FileName and FullPath fields of CommonHeaderClass object from
50 # XML Dom object of XmlCommonHeader, NameTag and FileName.
52 # @param CommonHeader The destine CommonClass object.
53 # @param XmlCommonHeader The source XML Dom object.
54 # @param NameTag The name tag in XML Dom object.
55 # @param FileName The file name of the XML file.
57 def SetIdentification(CommonHeader
, XmlCommonHeader
, NameTag
, FileName
):
58 XmlParentTag
= XmlNodeName(XmlCommonHeader
)
60 XmlTag
= XmlParentTag
+ "/" + NameTag
61 CommonHeader
.Name
= XmlElement(XmlCommonHeader
, XmlTag
)
63 XmlTag
= XmlParentTag
+ "/" + "GuidValue"
64 CommonHeader
.Guid
= XmlElement(XmlCommonHeader
, XmlTag
)
66 XmlTag
= XmlParentTag
+ "/" + "Version"
67 CommonHeader
.Version
= XmlElement(XmlCommonHeader
, XmlTag
)
69 CommonHeader
.FileName
= os
.path
.basename(FileName
)
70 CommonHeader
.FullPath
= os
.path
.abspath(FileName
)
73 ## Regular expression to match specification and value.
74 mReSpecification
= re
.compile(r
"(?P<Specification>\w+)\s+(?P<Value>\w*)")
76 ## Add specification to specification dictionary.
78 # Abstract specification name, value pair from Specification String and add them
79 # to specification dictionary.
81 # @param SpecificationDict The destine Specification dictionary.
82 # @param SpecificationString The source Specification String from which the
83 # specification name and value pair is abstracted.
85 def AddToSpecificationDict(SpecificationDict
, SpecificationString
):
86 """Abstract specification name, value pair from Specification String"""
87 for SpecificationMatch
in mReSpecification
.finditer(SpecificationString
):
88 Specification
= SpecificationMatch
.group("Specification")
89 Value
= SpecificationMatch
.group("Value")
90 SpecificationDict
[Specification
] = Value
92 ## Set all fields of CommonHeaderClass object.
94 # Set all attributes of CommonHeaderClass object from XML Dom object of
95 # XmlCommonHeader, NameTag and FileName.
97 # @param CommonHeader The destine CommonClass object.
98 # @param XmlCommonHeader The source XML Dom object.
99 # @param NameTag The name tag in XML Dom object.
100 # @param FileName The file name of the XML file.
102 def SetCommonHeader(CommonHeader
, XmlCommonHeader
):
103 """Set all attributes of CommonHeaderClass object from XmlCommonHeader"""
104 XmlParent
= XmlNodeName(XmlCommonHeader
)
106 XmlTag
= XmlParent
+ "/" + "Abstract"
107 CommonHeader
.Abstract
= XmlElement(XmlCommonHeader
, XmlTag
)
109 XmlTag
= XmlParent
+ "/" + "Description"
110 CommonHeader
.Description
= XmlElement(XmlCommonHeader
, XmlTag
)
112 XmlTag
= XmlParent
+ "/" + "Copyright"
113 CommonHeader
.Copyright
= XmlElement(XmlCommonHeader
, XmlTag
)
115 XmlTag
= XmlParent
+ "/" + "License"
116 CommonHeader
.License
= XmlElement(XmlCommonHeader
, XmlTag
)
118 XmlTag
= XmlParent
+ "/" + "Specification"
119 Specification
= XmlElement(XmlCommonHeader
, XmlTag
)
121 AddToSpecificationDict(CommonHeader
.Specification
, Specification
)
123 XmlTag
= XmlParent
+ "/" + "ModuleType"
124 CommonHeader
.ModuleType
= XmlElement(XmlCommonHeader
, XmlTag
)
127 ## Load a new Cloned Record class object.
129 # Read an input XML ClonedRecord DOM object and return an object of Cloned Record
130 # contained in the DOM object.
132 # @param XmlCloned A child XML DOM object in a Common XML DOM.
134 # @retvel ClonedRecord A new Cloned Record object created by XmlCloned.
136 def LoadClonedRecord(XmlCloned
):
137 ClonedRecord
= ClonedRecordClass()
140 ClonedRecord
.Id
= int(XmlAttribute(XmlCloned
, XmlTag
))
143 ClonedRecord
.FarGuid
= XmlAttribute(XmlCloned
, XmlTag
)
145 XmlTag
= "Cloned/PackageGuid"
146 ClonedRecord
.PackageGuid
= XmlElement(XmlCloned
, XmlTag
)
148 XmlTag
= "Cloned/PackageVersion"
149 ClonedRecord
.PackageVersion
= XmlElement(XmlCloned
, XmlTag
)
151 XmlTag
= "Cloned/ModuleGuid"
152 ClonedRecord
.ModuleGuid
= XmlElement(XmlCloned
, XmlTag
)
154 XmlTag
= "Cloned/ModuleVersion"
155 ClonedRecord
.ModuleVersion
= XmlElement(XmlCloned
, XmlTag
)
160 ## Load a new Guid/Protocol/Ppi common class object.
162 # Read an input XML Guid/Protocol/Ppi DOM object and return an object of
163 # Guid/Protocol/Ppi contained in the DOM object.
165 # @param XmlGuidProtocolPpiCommon A child XML DOM object in a Common XML DOM.
167 # @retvel GuidProtocolPpiCommon A new GuidProtocolPpiCommon class object
168 # created by XmlGuidProtocolPpiCommon.
170 def LoadGuidProtocolPpiCommon(XmlGuidProtocolPpiCommon
):
171 GuidProtocolPpiCommon
= GuidProtocolPpiCommonClass()
174 GuidProtocolPpiCommon
.Name
= XmlAttribute(XmlGuidProtocolPpiCommon
, XmlTag
)
176 XmlParent
= XmlNodeName(XmlGuidProtocolPpiCommon
)
177 if XmlParent
== "Entry":
178 XmlTag
= "%s/C_Name" % XmlParent
179 elif XmlParent
== "GuidCNames":
180 XmlTag
= "%s/GuidCName" % XmlParent
182 XmlTag
= "%s/%sCName" % (XmlParent
, XmlParent
)
184 GuidProtocolPpiCommon
.CName
= XmlElement(XmlGuidProtocolPpiCommon
, XmlTag
)
186 XmlTag
= XmlParent
+ "/" + "GuidValue"
187 GuidProtocolPpiCommon
.Guid
= XmlElement(XmlGuidProtocolPpiCommon
, XmlTag
)
189 if XmlParent
.endswith("Notify"):
190 GuidProtocolPpiCommon
.Notify
= True
192 XmlTag
= "GuidTypeList"
193 GuidTypes
= XmlAttribute(XmlGuidProtocolPpiCommon
, XmlTag
)
194 GuidProtocolPpiCommon
.GuidTypeList
= GuidTypes
.split()
196 XmlTag
= "SupModuleList"
197 SupModules
= XmlAttribute(XmlGuidProtocolPpiCommon
, XmlTag
)
198 GuidProtocolPpiCommon
.SupModuleList
= SupModules
.split()
200 SetCommon(GuidProtocolPpiCommon
, XmlGuidProtocolPpiCommon
)
202 return GuidProtocolPpiCommon
205 ## Load a new Pcd class object.
207 # Read an input XML Pcd DOM object and return an object of Pcd
208 # contained in the DOM object.
210 # @param XmlPcd A child XML DOM object in a Common XML DOM.
212 # @retvel Pcd A new Pcd object created by XmlPcd.
215 """Return a new PcdClass object equivalent to XmlPcd"""
218 XmlTag
= "PcdEntry/C_Name"
219 Pcd
.CName
= XmlElement(XmlPcd
, XmlTag
)
221 XmlTag
= "PcdEntry/Token"
222 Pcd
.Token
= XmlElement(XmlPcd
, XmlTag
)
224 XmlTag
= "PcdEntry/TokenSpaceGuidCName"
225 Pcd
.TokenSpaceGuidCName
= XmlElement(XmlPcd
, XmlTag
)
227 XmlTag
= "PcdEntry/DatumType"
228 Pcd
.DatumType
= XmlElement(XmlPcd
, XmlTag
)
230 XmlTag
= "PcdEntry/MaxDatumSize"
231 Pcd
.MaxDatumSize
= XmlElement(XmlPcd
, XmlTag
)
233 XmlTag
= "PcdEntry/DefaultValue"
234 Pcd
.DefaultValue
= XmlElement(XmlPcd
, XmlTag
)
236 XmlTag
= "PcdItemType"
237 Pcd
.ItemType
= XmlAttribute(XmlPcd
, XmlTag
)
239 XmlTag
= "PcdEntry/ValidUsage"
240 Pcd
.ValidUsage
= XmlElement(XmlPcd
, XmlTag
).split()
242 XmlTag
= "SupModuleList"
243 Pcd
.SupModuleList
= XmlAttribute(XmlPcd
, XmlTag
).split()
245 SetCommon(Pcd
, XmlPcd
)
250 ## Load a new LibraryClass class object.
252 # Read an input XML LibraryClass DOM object and return an object of LibraryClass
253 # contained in the DOM object.
255 # @param XmlLibraryClass A child XML DOM object in a Common XML DOM.
257 # @retvel LibraryClass A new LibraryClass object created by XmlLibraryClass.
259 def LoadLibraryClass(XmlLibraryClass
):
260 LibraryClass
= LibraryClassClass()
262 XmlTag
= "LibraryClass/Keyword"
263 LibraryClass
.LibraryClass
= XmlElement(XmlLibraryClass
, XmlTag
)
264 if LibraryClass
.LibraryClass
== "":
266 LibraryClass
.LibraryClass
= XmlAttribute(XmlLibraryClass
, XmlTag
)
268 XmlTag
= "LibraryClass/IncludeHeader"
269 LibraryClass
.IncludeHeader
= XmlElement(XmlLibraryClass
, XmlTag
)
271 XmlTag
= "RecommendedInstanceVersion"
272 RecommendedInstanceVersion
= XmlAttribute(XmlLibraryClass
, XmlTag
)
273 LibraryClass
.RecommendedInstanceVersion
= RecommendedInstanceVersion
275 XmlTag
= "RecommendedInstanceGuid"
276 RecommendedInstanceGuid
= XmlAttribute(XmlLibraryClass
, XmlTag
)
277 LibraryClass
.RecommendedInstanceGuid
= RecommendedInstanceGuid
279 XmlTag
= "SupModuleList"
280 SupModules
= XmlAttribute(XmlLibraryClass
, XmlTag
)
281 LibraryClass
.SupModuleList
= SupModules
.split()
283 SetCommon(LibraryClass
, XmlLibraryClass
)
288 ## Load a new Build Option class object.
290 # Read an input XML BuildOption DOM object and return an object of Build Option
291 # contained in the DOM object.
293 # @param XmlBuildOption A child XML DOM object in a Common XML DOM.
295 # @retvel BuildOption A new Build Option object created by XmlBuildOption.
297 def LoadBuildOption(XmlBuildOption
):
298 """Return a new BuildOptionClass object equivalent to XmlBuildOption"""
299 BuildOption
= BuildOptionClass()
301 BuildOption
.Option
= XmlElementData(XmlBuildOption
)
303 XmlTag
= "BuildTargets"
304 BuildOption
.BuildTargetList
= XmlAttribute(XmlBuildOption
, XmlTag
).split()
306 XmlTag
= "ToolChainFamily"
307 BuildOption
.ToolChainFamily
= XmlAttribute(XmlBuildOption
, XmlTag
)
310 BuildOption
.TagName
= XmlAttribute(XmlBuildOption
, XmlTag
)
313 BuildOption
.ToolCode
= XmlAttribute(XmlBuildOption
, XmlTag
)
315 XmlTag
= "SupArchList"
316 BuildOption
.SupArchList
= XmlAttribute(XmlBuildOption
, XmlTag
).split()
321 ## Load a new User Extensions class object.
323 # Read an input XML UserExtensions DOM object and return an object of User
324 # Extensions contained in the DOM object.
326 # @param XmlUserExtensions A child XML DOM object in a Common XML DOM.
328 # @retvel UserExtensions A new User Extensions object created by
331 def LoadUserExtensions(XmlUserExtensions
):
332 UserExtensions
= UserExtensionsClass()
335 UserExtensions
.UserID
= XmlAttribute(XmlUserExtensions
, XmlTag
)
337 XmlTag
= "Identifier"
338 UserExtensions
.Identifier
= XmlAttribute(XmlUserExtensions
, XmlTag
)
340 UserExtensions
.Content
= XmlElementData(XmlUserExtensions
)
342 return UserExtensions
345 ## Store content to a text file object.
347 # Write some text file content to a text file object. The contents may echo
348 # in screen in a verbose way.
350 # @param TextFile The text file object.
351 # @param Content The string object to be written to a text file.
353 def StoreTextFile(TextFile
, Content
):
354 EdkLogger
.verbose(Content
)
355 TextFile
.write(Content
)
358 ## Add item to a section.
360 # Add an Item with specific CPU architecture to section dictionary.
361 # The possible duplication is ensured to be removed.
363 # @param Section Section dictionary indexed by CPU architecture.
364 # @param Arch CPU architecture: Ia32, X64, Ipf, ARM, AARCH64, Ebc or Common.
365 # @param Item The Item to be added to section dictionary.
367 def AddToSection(Section
, Arch
, Item
):
368 SectionArch
= Section
.get(Arch
, [])
369 if Item
not in SectionArch
:
370 SectionArch
.append(Item
)
371 Section
[Arch
] = SectionArch
374 ## Get section contents.
376 # Return the content of section named SectionName.
377 # the contents is based on Methods and ObjectLists.
379 # @param SectionName The name of the section.
380 # @param Method A function returning a string item of an object.
381 # @param ObjectList The list of object.
383 # @retval Section The string content of a section.
385 def GetSection(SectionName
, Method
, ObjectList
):
386 SupportedArches
= ["common", "Ia32", "X64", "Ipf", "Ebc", "ARM", "AARCH64"]
388 for Object
in ObjectList
:
389 Item
= Method(Object
)
393 Arches
= Object
.SupArchList
395 AddToSection(SectionDict
, "common", Item
)
397 for Arch
in SupportedArches
:
398 if Arch
.upper() in Arches
:
399 AddToSection(SectionDict
, Arch
, Item
)
402 for Arch
in SupportedArches
:
403 SectionArch
= "\n".join(SectionDict
.get(Arch
, []))
404 if SectionArch
!= "":
405 Section
+= "[%s.%s]\n%s\n" % (SectionName
, Arch
, SectionArch
)
412 ## Store file header to a text file.
414 # Write standard file header to a text file. The content includes copyright,
415 # abstract, description and license extracted from CommonHeader class object.
417 # @param TextFile The text file object.
418 # @param CommonHeader The source CommonHeader class object.
420 def StoreHeader(TextFile
, CommonHeader
):
421 CopyRight
= CommonHeader
.Copyright
422 Abstract
= CommonHeader
.Abstract
423 Description
= CommonHeader
.Description
424 License
= CommonHeader
.License
426 Header
= "#/** @file\n#\n"
427 Header
+= "# " + Abstract
+ "\n#\n"
428 Header
+= "# " + Description
.strip().replace("\n", "\n# ") + "\n"
429 Header
+= "# " + CopyRight
+ "\n#\n"
430 Header
+= "# " + License
.replace("\n", "\n# ").replace(" ", " ")
431 Header
+= "\n#\n#**/\n\n"
433 StoreTextFile(TextFile
, Header
)
435 ## Store file header to a text file.
437 # Write Defines section to a text file. DefinesTupleList determines the content.
439 # @param TextFile The text file object.
440 # @param DefinesTupleList The list of (Tag, Value) to be added as one item.
442 def StoreDefinesSection(TextFile
, DefinesTupleList
):
443 Section
= "[Defines]\n"
444 for DefineItem
in DefinesTupleList
:
445 Section
+= " %-30s = %s\n" % DefineItem
448 StoreTextFile(TextFile
, Section
)
451 ## Return one User Extension section.
453 # Read the input UserExtentsions class object and return one section.
455 # @param UserExtensions An input UserExtensions class object.
457 # @retval UserExtensionSection A section representing UserExtensions object.
459 def GetUserExtensions(UserExtensions
):
460 UserId
= UserExtensions
.UserID
461 Identifier
= UserExtensions
.Identifier
462 Content
= UserExtensions
.Content
464 return "[UserExtensions.%s.%s]\n %s\n\n" % (UserId
, Identifier
, Content
)
466 ## Regular expression to match an equation.
467 mReEquation
= re
.compile(r
"\s*(\S+)\s*=\s*(\S*)\s*")
469 ## Return a value tuple matching information in a text fle.
471 # Parse the text file and return a value tuple corresponding to an input tag
472 # tuple. In case of any error, an tuple of empty strings is returned.
474 # @param FileName The file name of the text file.
475 # @param TagTuple A tuple of tags as the key to the value.
477 # @param ValueTupe The returned tuple corresponding to the tag tuple.
479 def GetTextFileInfo(FileName
, TagTuple
):
480 ValueTuple
= [""] * len(TagTuple
)
482 for Line
in open(FileName
):
483 Line
= Line
.split("#", 1)[0]
484 MatchEquation
= mReEquation
.match(Line
)
486 Tag
= MatchEquation
.group(1).upper()
487 Value
= MatchEquation
.group(2)
488 for Index
in range(len(TagTuple
)):
489 if TagTuple
[Index
] == Tag
:
490 ValueTuple
[Index
] = Value
492 EdkLogger
.info("IO Error in reading file %s" % FileName
)
497 ## Return a value tuple matching information in an XML fle.
499 # Parse the XML file and return a value tuple corresponding to an input tag
500 # tuple. In case of any error, an tuple of empty strings is returned.
502 # @param FileName The file name of the XML file.
503 # @param TagTuple A tuple of tags as the key to the value.
505 # @param ValueTupe The returned tuple corresponding to the tag tuple.
507 def GetXmlFileInfo(FileName
, TagTuple
):
508 XmlDom
= XmlParseFile(FileName
)
509 return tuple([XmlElement(XmlDom
, XmlTag
) for XmlTag
in TagTuple
])
512 ## Parse migration command line options
514 # Use standard Python module optparse to parse command line option of this tool.
516 # @param Source The source file type.
517 # @param Destinate The destinate file type.
519 # @retval Options A optparse object containing the parsed options.
520 # @retval InputFile Path of an source file to be migrated.
522 def MigrationOptionParser(Source
, Destinate
, ToolName
, VersionNumber
= 1.0):
523 # use clearer usage to override default usage message
524 UsageString
= "%s [-a] [-v|-q] [-o <output_file>] <input_file>" % ToolName
525 Version
= "%s Version %.2f" % (ToolName
, VersionNumber
)
526 Copyright
= "Copyright (c) 2007, Intel Corporation. All rights reserved."
528 Parser
= OptionParser(description
=Copyright
, version
=Version
, usage
=UsageString
)
529 Parser
.add_option("-o", "--output", dest
="OutputFile", help="The name of the %s file to be created." % Destinate
)
530 Parser
.add_option("-a", "--auto", dest
="AutoWrite", action
="store_true", default
=False, help="Automatically create the %s file using the name of the %s file and replacing file extension" % (Source
, Destinate
))
531 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
532 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
534 Options
, Args
= Parser
.parse_args()
538 EdkLogger
.setLevel(EdkLogger
.VERBOSE
)
540 EdkLogger
.setLevel(EdkLogger
.QUIET
)
542 EdkLogger
.setLevel(EdkLogger
.INFO
)
546 raise MigrationError(PARAMETER_MISSING
, name
="Input file", usage
=Parser
.get_usage())
548 raise MigrationError(PARAMETER_INVALID
, name
="Too many input files", usage
=Parser
.get_usage())
551 if not os
.path
.exists(InputFile
):
552 raise MigrationError(FILE_NOT_FOUND
, name
=InputFile
)
554 if Options
.OutputFile
:
555 if Options
.AutoWrite
:
556 raise MigrationError(OPTION_CONFLICT
, arg1
="-o", arg2
="-a", usage
=Parser
.get_usage())
558 if Options
.AutoWrite
:
559 Options
.OutputFile
= os
.path
.splitext(InputFile
)[0] + "." + Destinate
.lower()
561 raise MigrationError(OPTION_MISSING
, name
="-o", usage
=Parser
.get_usage())
563 return Options
, InputFile
565 # This acts like the main() function for the script, unless it is 'import'ed
566 # into another script.
567 if __name__
== '__main__':