2 # Contains several utilitities shared by migration tools.
4 # Copyright (c) 2007, 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.
20 from optparse
import OptionParser
21 from Common
.BuildToolError
import *
22 from XmlRoutines
import *
23 from CommonDataClass
.CommonClass
import *
25 ## Set all fields of CommonClass object.
27 # Set all attributes of CommonClass object from XML Dom object of XmlCommon.
29 # @param Common The destine CommonClass object.
30 # @param XmlCommon The source XML Dom object.
32 def SetCommon(Common
, XmlCommon
):
34 Common
.Usage
= XmlAttribute(XmlCommon
, XmlTag
).split()
36 XmlTag
= "FeatureFlag"
37 Common
.FeatureFlag
= XmlAttribute(XmlCommon
, XmlTag
)
39 XmlTag
= "SupArchList"
40 Common
.SupArchList
= XmlAttribute(XmlCommon
, XmlTag
).split()
42 XmlTag
= XmlNodeName(XmlCommon
) + "/" + "HelpText"
43 Common
.HelpText
= XmlElement(XmlCommon
, XmlTag
)
46 ## Set some fields of CommonHeaderClass object.
48 # Set Name, Guid, FileName and FullPath fields of CommonHeaderClass object from
49 # XML Dom object of XmlCommonHeader, NameTag and FileName.
51 # @param CommonHeader The destine CommonClass object.
52 # @param XmlCommonHeader The source XML Dom object.
53 # @param NameTag The name tag in XML Dom object.
54 # @param FileName The file name of the XML file.
56 def SetIdentification(CommonHeader
, XmlCommonHeader
, NameTag
, FileName
):
57 XmlParentTag
= XmlNodeName(XmlCommonHeader
)
59 XmlTag
= XmlParentTag
+ "/" + NameTag
60 CommonHeader
.Name
= XmlElement(XmlCommonHeader
, XmlTag
)
62 XmlTag
= XmlParentTag
+ "/" + "GuidValue"
63 CommonHeader
.Guid
= XmlElement(XmlCommonHeader
, XmlTag
)
65 XmlTag
= XmlParentTag
+ "/" + "Version"
66 CommonHeader
.Version
= XmlElement(XmlCommonHeader
, XmlTag
)
68 CommonHeader
.FileName
= os
.path
.basename(FileName
)
69 CommonHeader
.FullPath
= os
.path
.abspath(FileName
)
72 ## Regular expression to match specification and value.
73 mReSpecification
= re
.compile(r
"(?P<Specification>\w+)\s+(?P<Value>\w*)")
75 ## Add specification to specification dictionary.
77 # Abstract specification name, value pair from Specification String and add them
78 # to specification dictionary.
80 # @param SpecificationDict The destine Specification dictionary.
81 # @param SpecificationString The source Specification String from which the
82 # specification name and value pair is abstracted.
84 def AddToSpecificationDict(SpecificationDict
, SpecificationString
):
85 """Abstract specification name, value pair from Specification String"""
86 for SpecificationMatch
in mReSpecification
.finditer(SpecificationString
):
87 Specification
= SpecificationMatch
.group("Specification")
88 Value
= SpecificationMatch
.group("Value")
89 SpecificationDict
[Specification
] = Value
91 ## Set all fields of CommonHeaderClass object.
93 # Set all attributes of CommonHeaderClass object from XML Dom object of
94 # XmlCommonHeader, NameTag and FileName.
96 # @param CommonHeader The destine CommonClass object.
97 # @param XmlCommonHeader The source XML Dom object.
98 # @param NameTag The name tag in XML Dom object.
99 # @param FileName The file name of the XML file.
101 def SetCommonHeader(CommonHeader
, XmlCommonHeader
):
102 """Set all attributes of CommonHeaderClass object from XmlCommonHeader"""
103 XmlParent
= XmlNodeName(XmlCommonHeader
)
105 XmlTag
= XmlParent
+ "/" + "Abstract"
106 CommonHeader
.Abstract
= XmlElement(XmlCommonHeader
, XmlTag
)
108 XmlTag
= XmlParent
+ "/" + "Description"
109 CommonHeader
.Description
= XmlElement(XmlCommonHeader
, XmlTag
)
111 XmlTag
= XmlParent
+ "/" + "Copyright"
112 CommonHeader
.Copyright
= XmlElement(XmlCommonHeader
, XmlTag
)
114 XmlTag
= XmlParent
+ "/" + "License"
115 CommonHeader
.License
= XmlElement(XmlCommonHeader
, XmlTag
)
117 XmlTag
= XmlParent
+ "/" + "Specification"
118 Specification
= XmlElement(XmlCommonHeader
, XmlTag
)
120 AddToSpecificationDict(CommonHeader
.Specification
, Specification
)
122 XmlTag
= XmlParent
+ "/" + "ModuleType"
123 CommonHeader
.ModuleType
= XmlElement(XmlCommonHeader
, XmlTag
)
126 ## Load a new Cloned Record class object.
128 # Read an input XML ClonedRecord DOM object and return an object of Cloned Record
129 # contained in the DOM object.
131 # @param XmlCloned A child XML DOM object in a Common XML DOM.
133 # @retvel ClonedRecord A new Cloned Record object created by XmlCloned.
135 def LoadClonedRecord(XmlCloned
):
136 ClonedRecord
= ClonedRecordClass()
139 ClonedRecord
.Id
= int(XmlAttribute(XmlCloned
, XmlTag
))
142 ClonedRecord
.FarGuid
= XmlAttribute(XmlCloned
, XmlTag
)
144 XmlTag
= "Cloned/PackageGuid"
145 ClonedRecord
.PackageGuid
= XmlElement(XmlCloned
, XmlTag
)
147 XmlTag
= "Cloned/PackageVersion"
148 ClonedRecord
.PackageVersion
= XmlElement(XmlCloned
, XmlTag
)
150 XmlTag
= "Cloned/ModuleGuid"
151 ClonedRecord
.ModuleGuid
= XmlElement(XmlCloned
, XmlTag
)
153 XmlTag
= "Cloned/ModuleVersion"
154 ClonedRecord
.ModuleVersion
= XmlElement(XmlCloned
, XmlTag
)
159 ## Load a new Guid/Protocol/Ppi common class object.
161 # Read an input XML Guid/Protocol/Ppi DOM object and return an object of
162 # Guid/Protocol/Ppi contained in the DOM object.
164 # @param XmlGuidProtocolPpiCommon A child XML DOM object in a Common XML DOM.
166 # @retvel GuidProtocolPpiCommon A new GuidProtocolPpiCommon class object
167 # created by XmlGuidProtocolPpiCommon.
169 def LoadGuidProtocolPpiCommon(XmlGuidProtocolPpiCommon
):
170 GuidProtocolPpiCommon
= GuidProtocolPpiCommonClass()
173 GuidProtocolPpiCommon
.Name
= XmlAttribute(XmlGuidProtocolPpiCommon
, XmlTag
)
175 XmlParent
= XmlNodeName(XmlGuidProtocolPpiCommon
)
176 if XmlParent
== "Entry":
177 XmlTag
= "%s/C_Name" % XmlParent
178 elif XmlParent
== "GuidCNames":
179 XmlTag
= "%s/GuidCName" % XmlParent
181 XmlTag
= "%s/%sCName" % (XmlParent
, XmlParent
)
183 GuidProtocolPpiCommon
.CName
= XmlElement(XmlGuidProtocolPpiCommon
, XmlTag
)
185 XmlTag
= XmlParent
+ "/" + "GuidValue"
186 GuidProtocolPpiCommon
.Guid
= XmlElement(XmlGuidProtocolPpiCommon
, XmlTag
)
188 if XmlParent
.endswith("Notify"):
189 GuidProtocolPpiCommon
.Notify
= True
191 XmlTag
= "GuidTypeList"
192 GuidTypes
= XmlAttribute(XmlGuidProtocolPpiCommon
, XmlTag
)
193 GuidProtocolPpiCommon
.GuidTypeList
= GuidTypes
.split()
195 XmlTag
= "SupModuleList"
196 SupModules
= XmlAttribute(XmlGuidProtocolPpiCommon
, XmlTag
)
197 GuidProtocolPpiCommon
.SupModuleList
= SupModules
.split()
199 SetCommon(GuidProtocolPpiCommon
, XmlGuidProtocolPpiCommon
)
201 return GuidProtocolPpiCommon
204 ## Load a new Pcd class object.
206 # Read an input XML Pcd DOM object and return an object of Pcd
207 # contained in the DOM object.
209 # @param XmlPcd A child XML DOM object in a Common XML DOM.
211 # @retvel Pcd A new Pcd object created by XmlPcd.
214 """Return a new PcdClass object equivalent to XmlPcd"""
217 XmlTag
= "PcdEntry/C_Name"
218 Pcd
.CName
= XmlElement(XmlPcd
, XmlTag
)
220 XmlTag
= "PcdEntry/Token"
221 Pcd
.Token
= XmlElement(XmlPcd
, XmlTag
)
223 XmlTag
= "PcdEntry/TokenSpaceGuidCName"
224 Pcd
.TokenSpaceGuidCName
= XmlElement(XmlPcd
, XmlTag
)
226 XmlTag
= "PcdEntry/DatumType"
227 Pcd
.DatumType
= XmlElement(XmlPcd
, XmlTag
)
229 XmlTag
= "PcdEntry/MaxDatumSize"
230 Pcd
.MaxDatumSize
= XmlElement(XmlPcd
, XmlTag
)
232 XmlTag
= "PcdEntry/DefaultValue"
233 Pcd
.DefaultValue
= XmlElement(XmlPcd
, XmlTag
)
235 XmlTag
= "PcdItemType"
236 Pcd
.ItemType
= XmlAttribute(XmlPcd
, XmlTag
)
238 XmlTag
= "PcdEntry/ValidUsage"
239 Pcd
.ValidUsage
= XmlElement(XmlPcd
, XmlTag
).split()
241 XmlTag
= "SupModuleList"
242 Pcd
.SupModuleList
= XmlAttribute(XmlPcd
, XmlTag
).split()
244 SetCommon(Pcd
, XmlPcd
)
249 ## Load a new LibraryClass class object.
251 # Read an input XML LibraryClass DOM object and return an object of LibraryClass
252 # contained in the DOM object.
254 # @param XmlLibraryClass A child XML DOM object in a Common XML DOM.
256 # @retvel LibraryClass A new LibraryClass object created by XmlLibraryClass.
258 def LoadLibraryClass(XmlLibraryClass
):
259 LibraryClass
= LibraryClassClass()
261 XmlTag
= "LibraryClass/Keyword"
262 LibraryClass
.LibraryClass
= XmlElement(XmlLibraryClass
, XmlTag
)
263 if LibraryClass
.LibraryClass
== "":
265 LibraryClass
.LibraryClass
= XmlAttribute(XmlLibraryClass
, XmlTag
)
267 XmlTag
= "LibraryClass/IncludeHeader"
268 LibraryClass
.IncludeHeader
= XmlElement(XmlLibraryClass
, XmlTag
)
270 XmlTag
= "RecommendedInstanceVersion"
271 RecommendedInstanceVersion
= XmlAttribute(XmlLibraryClass
, XmlTag
)
272 LibraryClass
.RecommendedInstanceVersion
= RecommendedInstanceVersion
274 XmlTag
= "RecommendedInstanceGuid"
275 RecommendedInstanceGuid
= XmlAttribute(XmlLibraryClass
, XmlTag
)
276 LibraryClass
.RecommendedInstanceGuid
= RecommendedInstanceGuid
278 XmlTag
= "SupModuleList"
279 SupModules
= XmlAttribute(XmlLibraryClass
, XmlTag
)
280 LibraryClass
.SupModuleList
= SupModules
.split()
282 SetCommon(LibraryClass
, XmlLibraryClass
)
287 ## Load a new Build Option class object.
289 # Read an input XML BuildOption DOM object and return an object of Build Option
290 # contained in the DOM object.
292 # @param XmlBuildOption A child XML DOM object in a Common XML DOM.
294 # @retvel BuildOption A new Build Option object created by XmlBuildOption.
296 def LoadBuildOption(XmlBuildOption
):
297 """Return a new BuildOptionClass object equivalent to XmlBuildOption"""
298 BuildOption
= BuildOptionClass()
300 BuildOption
.Option
= XmlElementData(XmlBuildOption
)
302 XmlTag
= "BuildTargets"
303 BuildOption
.BuildTargetList
= XmlAttribute(XmlBuildOption
, XmlTag
).split()
305 XmlTag
= "ToolChainFamily"
306 BuildOption
.ToolChainFamily
= XmlAttribute(XmlBuildOption
, XmlTag
)
309 BuildOption
.TagName
= XmlAttribute(XmlBuildOption
, XmlTag
)
312 BuildOption
.ToolCode
= XmlAttribute(XmlBuildOption
, XmlTag
)
314 XmlTag
= "SupArchList"
315 BuildOption
.SupArchList
= XmlAttribute(XmlBuildOption
, XmlTag
).split()
320 ## Load a new User Extensions class object.
322 # Read an input XML UserExtensions DOM object and return an object of User
323 # Extensions contained in the DOM object.
325 # @param XmlUserExtensions A child XML DOM object in a Common XML DOM.
327 # @retvel UserExtensions A new User Extensions object created by
330 def LoadUserExtensions(XmlUserExtensions
):
331 UserExtensions
= UserExtensionsClass()
334 UserExtensions
.UserID
= XmlAttribute(XmlUserExtensions
, XmlTag
)
336 XmlTag
= "Identifier"
337 UserExtensions
.Identifier
= XmlAttribute(XmlUserExtensions
, XmlTag
)
339 UserExtensions
.Content
= XmlElementData(XmlUserExtensions
)
341 return UserExtensions
344 ## Store content to a text file object.
346 # Write some text file content to a text file object. The contents may echo
347 # in screen in a verbose way.
349 # @param TextFile The text file object.
350 # @param Content The string object to be written to a text file.
352 def StoreTextFile(TextFile
, Content
):
353 EdkLogger
.verbose(Content
)
354 TextFile
.write(Content
)
357 ## Add item to a section.
359 # Add an Item with specific CPU architecture to section dictionary.
360 # The possible duplication is ensured to be removed.
362 # @param Section Section dictionary indexed by CPU architecture.
363 # @param Arch CPU architecture: Ia32, X64, Ipf, ARM, AARCH64, Ebc or Common.
364 # @param Item The Item to be added to section dictionary.
366 def AddToSection(Section
, Arch
, Item
):
367 SectionArch
= Section
.get(Arch
, [])
368 if Item
not in SectionArch
:
369 SectionArch
.append(Item
)
370 Section
[Arch
] = SectionArch
373 ## Get section contents.
375 # Return the content of section named SectionName.
376 # the contents is based on Methods and ObjectLists.
378 # @param SectionName The name of the section.
379 # @param Method A function returning a string item of an object.
380 # @param ObjectList The list of object.
382 # @retval Section The string content of a section.
384 def GetSection(SectionName
, Method
, ObjectList
):
385 SupportedArches
= ["common", "Ia32", "X64", "Ipf", "Ebc", "ARM", "AARCH64"]
387 for Object
in ObjectList
:
388 Item
= Method(Object
)
392 Arches
= Object
.SupArchList
394 AddToSection(SectionDict
, "common", Item
)
396 for Arch
in SupportedArches
:
397 if Arch
.upper() in Arches
:
398 AddToSection(SectionDict
, Arch
, Item
)
401 for Arch
in SupportedArches
:
402 SectionArch
= "\n".join(SectionDict
.get(Arch
, []))
403 if SectionArch
!= "":
404 Section
+= "[%s.%s]\n%s\n" % (SectionName
, Arch
, SectionArch
)
411 ## Store file header to a text file.
413 # Write standard file header to a text file. The content includes copyright,
414 # abstract, description and license extracted from CommonHeader class object.
416 # @param TextFile The text file object.
417 # @param CommonHeader The source CommonHeader class object.
419 def StoreHeader(TextFile
, CommonHeader
):
420 CopyRight
= CommonHeader
.Copyright
421 Abstract
= CommonHeader
.Abstract
422 Description
= CommonHeader
.Description
423 License
= CommonHeader
.License
425 Header
= "#/** @file\n#\n"
426 Header
+= "# " + Abstract
+ "\n#\n"
427 Header
+= "# " + Description
.strip().replace("\n", "\n# ") + "\n"
428 Header
+= "# " + CopyRight
+ "\n#\n"
429 Header
+= "# " + License
.replace("\n", "\n# ").replace(" ", " ")
430 Header
+= "\n#\n#**/\n\n"
432 StoreTextFile(TextFile
, Header
)
434 ## Store file header to a text file.
436 # Write Defines section to a text file. DefinesTupleList determines the content.
438 # @param TextFile The text file object.
439 # @param DefinesTupleList The list of (Tag, Value) to be added as one item.
441 def StoreDefinesSection(TextFile
, DefinesTupleList
):
442 Section
= "[Defines]\n"
443 for DefineItem
in DefinesTupleList
:
444 Section
+= " %-30s = %s\n" % DefineItem
447 StoreTextFile(TextFile
, Section
)
450 ## Return one User Extension section.
452 # Read the input UserExtentsions class object and return one section.
454 # @param UserExtensions An input UserExtensions class object.
456 # @retval UserExtensionSection A section representing UserExtensions object.
458 def GetUserExtensions(UserExtensions
):
459 UserId
= UserExtensions
.UserID
460 Identifier
= UserExtensions
.Identifier
461 Content
= UserExtensions
.Content
463 return "[UserExtensions.%s.%s]\n %s\n\n" % (UserId
, Identifier
, Content
)
465 ## Regular expression to match an equation.
466 mReEquation
= re
.compile(r
"\s*(\S+)\s*=\s*(\S*)\s*")
468 ## Return a value tuple matching information in a text fle.
470 # Parse the text file and return a value tuple corresponding to an input tag
471 # tuple. In case of any error, an tuple of empty strings is returned.
473 # @param FileName The file name of the text file.
474 # @param TagTuple A tuple of tags as the key to the value.
476 # @param ValueTupe The returned tuple corresponding to the tag tuple.
478 def GetTextFileInfo(FileName
, TagTuple
):
479 ValueTuple
= [""] * len(TagTuple
)
481 for Line
in open(FileName
):
482 Line
= Line
.split("#", 1)[0]
483 MatchEquation
= mReEquation
.match(Line
)
485 Tag
= MatchEquation
.group(1).upper()
486 Value
= MatchEquation
.group(2)
487 for Index
in range(len(TagTuple
)):
488 if TagTuple
[Index
] == Tag
:
489 ValueTuple
[Index
] = Value
491 EdkLogger
.info("IO Error in reading file %s" % FileName
)
496 ## Return a value tuple matching information in an XML fle.
498 # Parse the XML file and return a value tuple corresponding to an input tag
499 # tuple. In case of any error, an tuple of empty strings is returned.
501 # @param FileName The file name of the XML file.
502 # @param TagTuple A tuple of tags as the key to the value.
504 # @param ValueTupe The returned tuple corresponding to the tag tuple.
506 def GetXmlFileInfo(FileName
, TagTuple
):
507 XmlDom
= XmlParseFile(FileName
)
508 return tuple([XmlElement(XmlDom
, XmlTag
) for XmlTag
in TagTuple
])
511 ## Parse migration command line options
513 # Use standard Python module optparse to parse command line option of this tool.
515 # @param Source The source file type.
516 # @param Destinate The destinate file type.
518 # @retval Options A optparse object containing the parsed options.
519 # @retval InputFile Path of an source file to be migrated.
521 def MigrationOptionParser(Source
, Destinate
, ToolName
, VersionNumber
= 1.0):
522 # use clearer usage to override default usage message
523 UsageString
= "%s [-a] [-v|-q] [-o <output_file>] <input_file>" % ToolName
524 Version
= "%s Version %.2f" % (ToolName
, VersionNumber
)
525 Copyright
= "Copyright (c) 2007, Intel Corporation. All rights reserved."
527 Parser
= OptionParser(description
=Copyright
, version
=Version
, usage
=UsageString
)
528 Parser
.add_option("-o", "--output", dest
="OutputFile", help="The name of the %s file to be created." % Destinate
)
529 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
))
530 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
531 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
533 Options
, Args
= Parser
.parse_args()
537 EdkLogger
.setLevel(EdkLogger
.VERBOSE
)
539 EdkLogger
.setLevel(EdkLogger
.QUIET
)
541 EdkLogger
.setLevel(EdkLogger
.INFO
)
545 raise MigrationError(PARAMETER_MISSING
, name
="Input file", usage
=Parser
.get_usage())
547 raise MigrationError(PARAMETER_INVALID
, name
="Too many input files", usage
=Parser
.get_usage())
550 if not os
.path
.exists(InputFile
):
551 raise MigrationError(FILE_NOT_FOUND
, name
=InputFile
)
553 if Options
.OutputFile
:
554 if Options
.AutoWrite
:
555 raise MigrationError(OPTION_CONFLICT
, arg1
="-o", arg2
="-a", usage
=Parser
.get_usage())
557 if Options
.AutoWrite
:
558 Options
.OutputFile
= os
.path
.splitext(InputFile
)[0] + "." + Destinate
.lower()
560 raise MigrationError(OPTION_MISSING
, name
="-o", usage
=Parser
.get_usage())
562 return Options
, InputFile
564 # This acts like the main() function for the script, unless it is 'import'ed
565 # into another script.
566 if __name__
== '__main__':