## @file # Contains several utilitities shared by migration tools. # # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
# This program and the accompanying materials # 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 Common.LongFilePathOs as os import re import EdkLogger from optparse import OptionParser from Common.BuildToolError import * from XmlRoutines import * from CommonDataClass.CommonClass import * from Common.LongFilePathSupport import OpenLongFilePath as open ## 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\w+)\s+(?P\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/%sCName" % (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, AARCH64, 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", "AARCH64"] 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 ] " % 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