2009-07-17 11:10:31 +02:00
## @file
# Contains several utilitities shared by migration tools.
#
2010-05-18 07:04:32 +02:00
# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
2009-07-17 11:10:31 +02:00
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
# Import Modules
#
import os
import re
import EdkLogger
from optparse import OptionParser
from Common . BuildToolError import *
from XmlRoutines import *
from CommonDataClass . CommonClass import *
## Set all fields of CommonClass object.
#
# Set all attributes of CommonClass object from XML Dom object of XmlCommon.
#
# @param Common The destine CommonClass object.
# @param XmlCommon The source XML Dom object.
#
def SetCommon ( Common , XmlCommon ) :
XmlTag = " Usage "
Common . Usage = XmlAttribute ( XmlCommon , XmlTag ) . split ( )
XmlTag = " FeatureFlag "
Common . FeatureFlag = XmlAttribute ( XmlCommon , XmlTag )
XmlTag = " SupArchList "
Common . SupArchList = XmlAttribute ( XmlCommon , XmlTag ) . split ( )
XmlTag = XmlNodeName ( XmlCommon ) + " / " + " HelpText "
Common . HelpText = XmlElement ( XmlCommon , XmlTag )
## Set some fields of CommonHeaderClass object.
#
# Set Name, Guid, FileName and FullPath fields of CommonHeaderClass object from
# XML Dom object of XmlCommonHeader, NameTag and FileName.
#
# @param CommonHeader The destine CommonClass object.
# @param XmlCommonHeader The source XML Dom object.
# @param NameTag The name tag in XML Dom object.
# @param FileName The file name of the XML file.
#
def SetIdentification ( CommonHeader , XmlCommonHeader , NameTag , FileName ) :
XmlParentTag = XmlNodeName ( XmlCommonHeader )
XmlTag = XmlParentTag + " / " + NameTag
CommonHeader . Name = XmlElement ( XmlCommonHeader , XmlTag )
XmlTag = XmlParentTag + " / " + " GuidValue "
CommonHeader . Guid = XmlElement ( XmlCommonHeader , XmlTag )
XmlTag = XmlParentTag + " / " + " Version "
CommonHeader . Version = XmlElement ( XmlCommonHeader , XmlTag )
CommonHeader . FileName = os . path . basename ( FileName )
CommonHeader . FullPath = os . path . abspath ( FileName )
## Regular expression to match specification and value.
mReSpecification = re . compile ( r " (?P<Specification> \ w+) \ s+(?P<Value> \ w*) " )
## Add specification to specification dictionary.
#
# Abstract specification name, value pair from Specification String and add them
# to specification dictionary.
#
# @param SpecificationDict The destine Specification dictionary.
# @param SpecificationString The source Specification String from which the
# specification name and value pair is abstracted.
#
def AddToSpecificationDict ( SpecificationDict , SpecificationString ) :
""" Abstract specification name, value pair from Specification String """
for SpecificationMatch in mReSpecification . finditer ( SpecificationString ) :
Specification = SpecificationMatch . group ( " Specification " )
Value = SpecificationMatch . group ( " Value " )
SpecificationDict [ Specification ] = Value
## Set all fields of CommonHeaderClass object.
#
# Set all attributes of CommonHeaderClass object from XML Dom object of
# XmlCommonHeader, NameTag and FileName.
#
# @param CommonHeader The destine CommonClass object.
# @param XmlCommonHeader The source XML Dom object.
# @param NameTag The name tag in XML Dom object.
# @param FileName The file name of the XML file.
#
def SetCommonHeader ( CommonHeader , XmlCommonHeader ) :
""" Set all attributes of CommonHeaderClass object from XmlCommonHeader """
XmlParent = XmlNodeName ( XmlCommonHeader )
XmlTag = XmlParent + " / " + " Abstract "
CommonHeader . Abstract = XmlElement ( XmlCommonHeader , XmlTag )
XmlTag = XmlParent + " / " + " Description "
CommonHeader . Description = XmlElement ( XmlCommonHeader , XmlTag )
XmlTag = XmlParent + " / " + " Copyright "
CommonHeader . Copyright = XmlElement ( XmlCommonHeader , XmlTag )
XmlTag = XmlParent + " / " + " License "
CommonHeader . License = XmlElement ( XmlCommonHeader , XmlTag )
XmlTag = XmlParent + " / " + " Specification "
Specification = XmlElement ( XmlCommonHeader , XmlTag )
AddToSpecificationDict ( CommonHeader . Specification , Specification )
XmlTag = XmlParent + " / " + " ModuleType "
CommonHeader . ModuleType = XmlElement ( XmlCommonHeader , XmlTag )
## Load a new Cloned Record class object.
#
# Read an input XML ClonedRecord DOM object and return an object of Cloned Record
# contained in the DOM object.
#
# @param XmlCloned A child XML DOM object in a Common XML DOM.
#
# @retvel ClonedRecord A new Cloned Record object created by XmlCloned.
#
def LoadClonedRecord ( XmlCloned ) :
ClonedRecord = ClonedRecordClass ( )
XmlTag = " Id "
ClonedRecord . Id = int ( XmlAttribute ( XmlCloned , XmlTag ) )
XmlTag = " FarGuid "
ClonedRecord . FarGuid = XmlAttribute ( XmlCloned , XmlTag )
XmlTag = " Cloned/PackageGuid "
ClonedRecord . PackageGuid = XmlElement ( XmlCloned , XmlTag )
XmlTag = " Cloned/PackageVersion "
ClonedRecord . PackageVersion = XmlElement ( XmlCloned , XmlTag )
XmlTag = " Cloned/ModuleGuid "
ClonedRecord . ModuleGuid = XmlElement ( XmlCloned , XmlTag )
XmlTag = " Cloned/ModuleVersion "
ClonedRecord . ModuleVersion = XmlElement ( XmlCloned , XmlTag )
return ClonedRecord
## Load a new Guid/Protocol/Ppi common class object.
#
# Read an input XML Guid/Protocol/Ppi DOM object and return an object of
# Guid/Protocol/Ppi contained in the DOM object.
#
# @param XmlGuidProtocolPpiCommon A child XML DOM object in a Common XML DOM.
#
# @retvel GuidProtocolPpiCommon A new GuidProtocolPpiCommon class object
# created by XmlGuidProtocolPpiCommon.
#
def LoadGuidProtocolPpiCommon ( XmlGuidProtocolPpiCommon ) :
GuidProtocolPpiCommon = GuidProtocolPpiCommonClass ( )
XmlTag = " Name "
GuidProtocolPpiCommon . Name = XmlAttribute ( XmlGuidProtocolPpiCommon , XmlTag )
XmlParent = XmlNodeName ( XmlGuidProtocolPpiCommon )
if XmlParent == " Entry " :
XmlTag = " %s /C_Name " % XmlParent
elif XmlParent == " GuidCNames " :
XmlTag = " %s /GuidCName " % XmlParent
else :
XmlTag = " %s / %s CName " % ( XmlParent , XmlParent )
GuidProtocolPpiCommon . CName = XmlElement ( XmlGuidProtocolPpiCommon , XmlTag )
XmlTag = XmlParent + " / " + " GuidValue "
GuidProtocolPpiCommon . Guid = XmlElement ( XmlGuidProtocolPpiCommon , XmlTag )
if XmlParent . endswith ( " Notify " ) :
GuidProtocolPpiCommon . Notify = True
XmlTag = " GuidTypeList "
GuidTypes = XmlAttribute ( XmlGuidProtocolPpiCommon , XmlTag )
GuidProtocolPpiCommon . GuidTypeList = GuidTypes . split ( )
XmlTag = " SupModuleList "
SupModules = XmlAttribute ( XmlGuidProtocolPpiCommon , XmlTag )
GuidProtocolPpiCommon . SupModuleList = SupModules . split ( )
SetCommon ( GuidProtocolPpiCommon , XmlGuidProtocolPpiCommon )
return GuidProtocolPpiCommon
## Load a new Pcd class object.
#
# Read an input XML Pcd DOM object and return an object of Pcd
# contained in the DOM object.
#
# @param XmlPcd A child XML DOM object in a Common XML DOM.
#
# @retvel Pcd A new Pcd object created by XmlPcd.
#
def LoadPcd ( XmlPcd ) :
""" Return a new PcdClass object equivalent to XmlPcd """
Pcd = PcdClass ( )
XmlTag = " PcdEntry/C_Name "
Pcd . CName = XmlElement ( XmlPcd , XmlTag )
XmlTag = " PcdEntry/Token "
Pcd . Token = XmlElement ( XmlPcd , XmlTag )
XmlTag = " PcdEntry/TokenSpaceGuidCName "
Pcd . TokenSpaceGuidCName = XmlElement ( XmlPcd , XmlTag )
XmlTag = " PcdEntry/DatumType "
Pcd . DatumType = XmlElement ( XmlPcd , XmlTag )
XmlTag = " PcdEntry/MaxDatumSize "
Pcd . MaxDatumSize = XmlElement ( XmlPcd , XmlTag )
XmlTag = " PcdEntry/DefaultValue "
Pcd . DefaultValue = XmlElement ( XmlPcd , XmlTag )
XmlTag = " PcdItemType "
Pcd . ItemType = XmlAttribute ( XmlPcd , XmlTag )
XmlTag = " PcdEntry/ValidUsage "
Pcd . ValidUsage = XmlElement ( XmlPcd , XmlTag ) . split ( )
XmlTag = " SupModuleList "
Pcd . SupModuleList = XmlAttribute ( XmlPcd , XmlTag ) . split ( )
SetCommon ( Pcd , XmlPcd )
return Pcd
## Load a new LibraryClass class object.
#
# Read an input XML LibraryClass DOM object and return an object of LibraryClass
# contained in the DOM object.
#
# @param XmlLibraryClass A child XML DOM object in a Common XML DOM.
#
# @retvel LibraryClass A new LibraryClass object created by XmlLibraryClass.
#
def LoadLibraryClass ( XmlLibraryClass ) :
LibraryClass = LibraryClassClass ( )
XmlTag = " LibraryClass/Keyword "
LibraryClass . LibraryClass = XmlElement ( XmlLibraryClass , XmlTag )
if LibraryClass . LibraryClass == " " :
XmlTag = " Name "
LibraryClass . LibraryClass = XmlAttribute ( XmlLibraryClass , XmlTag )
XmlTag = " LibraryClass/IncludeHeader "
LibraryClass . IncludeHeader = XmlElement ( XmlLibraryClass , XmlTag )
XmlTag = " RecommendedInstanceVersion "
RecommendedInstanceVersion = XmlAttribute ( XmlLibraryClass , XmlTag )
LibraryClass . RecommendedInstanceVersion = RecommendedInstanceVersion
XmlTag = " RecommendedInstanceGuid "
RecommendedInstanceGuid = XmlAttribute ( XmlLibraryClass , XmlTag )
LibraryClass . RecommendedInstanceGuid = RecommendedInstanceGuid
XmlTag = " SupModuleList "
SupModules = XmlAttribute ( XmlLibraryClass , XmlTag )
LibraryClass . SupModuleList = SupModules . split ( )
SetCommon ( LibraryClass , XmlLibraryClass )
return LibraryClass
## Load a new Build Option class object.
#
# Read an input XML BuildOption DOM object and return an object of Build Option
# contained in the DOM object.
#
# @param XmlBuildOption A child XML DOM object in a Common XML DOM.
#
# @retvel BuildOption A new Build Option object created by XmlBuildOption.
#
def LoadBuildOption ( XmlBuildOption ) :
""" Return a new BuildOptionClass object equivalent to XmlBuildOption """
BuildOption = BuildOptionClass ( )
BuildOption . Option = XmlElementData ( XmlBuildOption )
XmlTag = " BuildTargets "
BuildOption . BuildTargetList = XmlAttribute ( XmlBuildOption , XmlTag ) . split ( )
XmlTag = " ToolChainFamily "
BuildOption . ToolChainFamily = XmlAttribute ( XmlBuildOption , XmlTag )
XmlTag = " TagName "
BuildOption . TagName = XmlAttribute ( XmlBuildOption , XmlTag )
XmlTag = " ToolCode "
BuildOption . ToolCode = XmlAttribute ( XmlBuildOption , XmlTag )
XmlTag = " SupArchList "
BuildOption . SupArchList = XmlAttribute ( XmlBuildOption , XmlTag ) . split ( )
return BuildOption
## Load a new User Extensions class object.
#
# Read an input XML UserExtensions DOM object and return an object of User
# Extensions contained in the DOM object.
#
# @param XmlUserExtensions A child XML DOM object in a Common XML DOM.
#
# @retvel UserExtensions A new User Extensions object created by
# XmlUserExtensions.
#
def LoadUserExtensions ( XmlUserExtensions ) :
UserExtensions = UserExtensionsClass ( )
XmlTag = " UserID "
UserExtensions . UserID = XmlAttribute ( XmlUserExtensions , XmlTag )
XmlTag = " Identifier "
UserExtensions . Identifier = XmlAttribute ( XmlUserExtensions , XmlTag )
UserExtensions . Content = XmlElementData ( XmlUserExtensions )
return UserExtensions
## Store content to a text file object.
#
# Write some text file content to a text file object. The contents may echo
# in screen in a verbose way.
#
# @param TextFile The text file object.
# @param Content The string object to be written to a text file.
#
def StoreTextFile ( TextFile , Content ) :
EdkLogger . verbose ( Content )
TextFile . write ( Content )
## Add item to a section.
#
# Add an Item with specific CPU architecture to section dictionary.
# The possible duplication is ensured to be removed.
#
# @param Section Section dictionary indexed by CPU architecture.
# @param Arch CPU architecture: Ia32, X64, Ipf, ARM, Ebc or Common.
# @param Item The Item to be added to section dictionary.
#
def AddToSection ( Section , Arch , Item ) :
SectionArch = Section . get ( Arch , [ ] )
if Item not in SectionArch :
SectionArch . append ( Item )
Section [ Arch ] = SectionArch
## Get section contents.
#
# Return the content of section named SectionName.
# the contents is based on Methods and ObjectLists.
#
# @param SectionName The name of the section.
# @param Method A function returning a string item of an object.
# @param ObjectList The list of object.
#
# @retval Section The string content of a section.
#
def GetSection ( SectionName , Method , ObjectList ) :
SupportedArches = [ " common " , " Ia32 " , " X64 " , " Ipf " , " Ebc " , " ARM " ]
SectionDict = { }
for Object in ObjectList :
Item = Method ( Object )
if Item == " " :
continue
Item = " %s " % Item
Arches = Object . SupArchList
if len ( Arches ) == 0 :
AddToSection ( SectionDict , " common " , Item )
else :
for Arch in SupportedArches :
if Arch . upper ( ) in Arches :
AddToSection ( SectionDict , Arch , Item )
Section = " "
for Arch in SupportedArches :
SectionArch = " \n " . join ( SectionDict . get ( Arch , [ ] ) )
if SectionArch != " " :
Section + = " [ %s . %s ] \n %s \n " % ( SectionName , Arch , SectionArch )
Section + = " \n "
if Section != " " :
Section + = " \n "
return Section
## Store file header to a text file.
#
# Write standard file header to a text file. The content includes copyright,
# abstract, description and license extracted from CommonHeader class object.
#
# @param TextFile The text file object.
# @param CommonHeader The source CommonHeader class object.
#
def StoreHeader ( TextFile , CommonHeader ) :
CopyRight = CommonHeader . Copyright
Abstract = CommonHeader . Abstract
Description = CommonHeader . Description
License = CommonHeader . License
Header = " #/** @file \n # \n "
Header + = " # " + Abstract + " \n # \n "
Header + = " # " + Description . strip ( ) . replace ( " \n " , " \n # " ) + " \n "
Header + = " # " + CopyRight + " \n # \n "
Header + = " # " + License . replace ( " \n " , " \n # " ) . replace ( " " , " " )
Header + = " \n # \n #**/ \n \n "
StoreTextFile ( TextFile , Header )
## Store file header to a text file.
#
# Write Defines section to a text file. DefinesTupleList determines the content.
#
# @param TextFile The text file object.
# @param DefinesTupleList The list of (Tag, Value) to be added as one item.
#
def StoreDefinesSection ( TextFile , DefinesTupleList ) :
Section = " [Defines] \n "
for DefineItem in DefinesTupleList :
Section + = " %-30s = %s \n " % DefineItem
Section + = " \n \n "
StoreTextFile ( TextFile , Section )
## Return one User Extension section.
#
# Read the input UserExtentsions class object and return one section.
#
# @param UserExtensions An input UserExtensions class object.
#
# @retval UserExtensionSection A section representing UserExtensions object.
#
def GetUserExtensions ( UserExtensions ) :
UserId = UserExtensions . UserID
Identifier = UserExtensions . Identifier
Content = UserExtensions . Content
return " [UserExtensions. %s . %s ] \n %s \n \n " % ( UserId , Identifier , Content )
## Regular expression to match an equation.
mReEquation = re . compile ( r " \ s*( \ S+) \ s*= \ s*( \ S*) \ s* " )
## Return a value tuple matching information in a text fle.
#
# Parse the text file and return a value tuple corresponding to an input tag
# tuple. In case of any error, an tuple of empty strings is returned.
#
# @param FileName The file name of the text file.
# @param TagTuple A tuple of tags as the key to the value.
#
# @param ValueTupe The returned tuple corresponding to the tag tuple.
#
def GetTextFileInfo ( FileName , TagTuple ) :
ValueTuple = [ " " ] * len ( TagTuple )
try :
for Line in open ( FileName ) :
Line = Line . split ( " # " , 1 ) [ 0 ]
MatchEquation = mReEquation . match ( Line )
if MatchEquation :
Tag = MatchEquation . group ( 1 ) . upper ( )
Value = MatchEquation . group ( 2 )
for Index in range ( len ( TagTuple ) ) :
if TagTuple [ Index ] == Tag :
ValueTuple [ Index ] = Value
except :
EdkLogger . info ( " IO Error in reading file %s " % FileName )
return ValueTuple
## Return a value tuple matching information in an XML fle.
#
# Parse the XML file and return a value tuple corresponding to an input tag
# tuple. In case of any error, an tuple of empty strings is returned.
#
# @param FileName The file name of the XML file.
# @param TagTuple A tuple of tags as the key to the value.
#
# @param ValueTupe The returned tuple corresponding to the tag tuple.
#
def GetXmlFileInfo ( FileName , TagTuple ) :
XmlDom = XmlParseFile ( FileName )
return tuple ( [ XmlElement ( XmlDom , XmlTag ) for XmlTag in TagTuple ] )
## Parse migration command line options
#
# Use standard Python module optparse to parse command line option of this tool.
#
# @param Source The source file type.
# @param Destinate The destinate file type.
#
# @retval Options A optparse object containing the parsed options.
# @retval InputFile Path of an source file to be migrated.
#
def MigrationOptionParser ( Source , Destinate , ToolName , VersionNumber = 1.0 ) :
# use clearer usage to override default usage message
UsageString = " %s [-a] [-v|-q] [-o <output_file>] <input_file> " % ToolName
Version = " %s Version %.2f " % ( ToolName , VersionNumber )
Copyright = " Copyright (c) 2007, Intel Corporation. All rights reserved. "
Parser = OptionParser ( description = Copyright , version = Version , usage = UsageString )
Parser . add_option ( " -o " , " --output " , dest = " OutputFile " , help = " The name of the %s file to be created. " % Destinate )
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 ) )
Parser . add_option ( " -q " , " --quiet " , action = " store_true " , type = None , help = " Disable all messages except FATAL ERRORS. " )
Parser . add_option ( " -v " , " --verbose " , action = " store_true " , type = None , help = " Turn on verbose output with informational messages printed. " )
Options , Args = Parser . parse_args ( )
# Set logging level
if Options . verbose :
EdkLogger . setLevel ( EdkLogger . VERBOSE )
elif Options . quiet :
EdkLogger . setLevel ( EdkLogger . QUIET )
else :
EdkLogger . setLevel ( EdkLogger . INFO )
# error check
if len ( Args ) == 0 :
raise MigrationError ( PARAMETER_MISSING , name = " Input file " , usage = Parser . get_usage ( ) )
if len ( Args ) > 1 :
raise MigrationError ( PARAMETER_INVALID , name = " Too many input files " , usage = Parser . get_usage ( ) )
InputFile = Args [ 0 ]
if not os . path . exists ( InputFile ) :
raise MigrationError ( FILE_NOT_FOUND , name = InputFile )
if Options . OutputFile :
if Options . AutoWrite :
raise MigrationError ( OPTION_CONFLICT , arg1 = " -o " , arg2 = " -a " , usage = Parser . get_usage ( ) )
else :
if Options . AutoWrite :
Options . OutputFile = os . path . splitext ( InputFile ) [ 0 ] + " . " + Destinate . lower ( )
else :
raise MigrationError ( OPTION_MISSING , name = " -o " , usage = Parser . get_usage ( ) )
return Options , InputFile
# This acts like the main() function for the script, unless it is 'import'ed
# into another script.
if __name__ == ' __main__ ' :
pass