]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/MigrationUtilities.py
There is a limitation on WINDOWS OS for the length of entire file path can’t be large...
[mirror_edk2.git] / BaseTools / Source / Python / Common / MigrationUtilities.py
1 ## @file
2 # Contains several utilitities shared by migration tools.
3 #
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
9 #
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.
12 #
13
14 ##
15 # Import Modules
16 #
17 import Common.LongFilePathOs as os
18 import re
19 import EdkLogger
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
25
26 ## Set all fields of CommonClass object.
27 #
28 # Set all attributes of CommonClass object from XML Dom object of XmlCommon.
29 #
30 # @param Common The destine CommonClass object.
31 # @param XmlCommon The source XML Dom object.
32 #
33 def SetCommon(Common, XmlCommon):
34 XmlTag = "Usage"
35 Common.Usage = XmlAttribute(XmlCommon, XmlTag).split()
36
37 XmlTag = "FeatureFlag"
38 Common.FeatureFlag = XmlAttribute(XmlCommon, XmlTag)
39
40 XmlTag = "SupArchList"
41 Common.SupArchList = XmlAttribute(XmlCommon, XmlTag).split()
42
43 XmlTag = XmlNodeName(XmlCommon) + "/" + "HelpText"
44 Common.HelpText = XmlElement(XmlCommon, XmlTag)
45
46
47 ## Set some fields of CommonHeaderClass object.
48 #
49 # Set Name, Guid, FileName and FullPath fields of CommonHeaderClass object from
50 # XML Dom object of XmlCommonHeader, NameTag and FileName.
51 #
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.
56 #
57 def SetIdentification(CommonHeader, XmlCommonHeader, NameTag, FileName):
58 XmlParentTag = XmlNodeName(XmlCommonHeader)
59
60 XmlTag = XmlParentTag + "/" + NameTag
61 CommonHeader.Name = XmlElement(XmlCommonHeader, XmlTag)
62
63 XmlTag = XmlParentTag + "/" + "GuidValue"
64 CommonHeader.Guid = XmlElement(XmlCommonHeader, XmlTag)
65
66 XmlTag = XmlParentTag + "/" + "Version"
67 CommonHeader.Version = XmlElement(XmlCommonHeader, XmlTag)
68
69 CommonHeader.FileName = os.path.basename(FileName)
70 CommonHeader.FullPath = os.path.abspath(FileName)
71
72
73 ## Regular expression to match specification and value.
74 mReSpecification = re.compile(r"(?P<Specification>\w+)\s+(?P<Value>\w*)")
75
76 ## Add specification to specification dictionary.
77 #
78 # Abstract specification name, value pair from Specification String and add them
79 # to specification dictionary.
80 #
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.
84 #
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
91
92 ## Set all fields of CommonHeaderClass object.
93 #
94 # Set all attributes of CommonHeaderClass object from XML Dom object of
95 # XmlCommonHeader, NameTag and FileName.
96 #
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.
101 #
102 def SetCommonHeader(CommonHeader, XmlCommonHeader):
103 """Set all attributes of CommonHeaderClass object from XmlCommonHeader"""
104 XmlParent = XmlNodeName(XmlCommonHeader)
105
106 XmlTag = XmlParent + "/" + "Abstract"
107 CommonHeader.Abstract = XmlElement(XmlCommonHeader, XmlTag)
108
109 XmlTag = XmlParent + "/" + "Description"
110 CommonHeader.Description = XmlElement(XmlCommonHeader, XmlTag)
111
112 XmlTag = XmlParent + "/" + "Copyright"
113 CommonHeader.Copyright = XmlElement(XmlCommonHeader, XmlTag)
114
115 XmlTag = XmlParent + "/" + "License"
116 CommonHeader.License = XmlElement(XmlCommonHeader, XmlTag)
117
118 XmlTag = XmlParent + "/" + "Specification"
119 Specification = XmlElement(XmlCommonHeader, XmlTag)
120
121 AddToSpecificationDict(CommonHeader.Specification, Specification)
122
123 XmlTag = XmlParent + "/" + "ModuleType"
124 CommonHeader.ModuleType = XmlElement(XmlCommonHeader, XmlTag)
125
126
127 ## Load a new Cloned Record class object.
128 #
129 # Read an input XML ClonedRecord DOM object and return an object of Cloned Record
130 # contained in the DOM object.
131 #
132 # @param XmlCloned A child XML DOM object in a Common XML DOM.
133 #
134 # @retvel ClonedRecord A new Cloned Record object created by XmlCloned.
135 #
136 def LoadClonedRecord(XmlCloned):
137 ClonedRecord = ClonedRecordClass()
138
139 XmlTag = "Id"
140 ClonedRecord.Id = int(XmlAttribute(XmlCloned, XmlTag))
141
142 XmlTag = "FarGuid"
143 ClonedRecord.FarGuid = XmlAttribute(XmlCloned, XmlTag)
144
145 XmlTag = "Cloned/PackageGuid"
146 ClonedRecord.PackageGuid = XmlElement(XmlCloned, XmlTag)
147
148 XmlTag = "Cloned/PackageVersion"
149 ClonedRecord.PackageVersion = XmlElement(XmlCloned, XmlTag)
150
151 XmlTag = "Cloned/ModuleGuid"
152 ClonedRecord.ModuleGuid = XmlElement(XmlCloned, XmlTag)
153
154 XmlTag = "Cloned/ModuleVersion"
155 ClonedRecord.ModuleVersion = XmlElement(XmlCloned, XmlTag)
156
157 return ClonedRecord
158
159
160 ## Load a new Guid/Protocol/Ppi common class object.
161 #
162 # Read an input XML Guid/Protocol/Ppi DOM object and return an object of
163 # Guid/Protocol/Ppi contained in the DOM object.
164 #
165 # @param XmlGuidProtocolPpiCommon A child XML DOM object in a Common XML DOM.
166 #
167 # @retvel GuidProtocolPpiCommon A new GuidProtocolPpiCommon class object
168 # created by XmlGuidProtocolPpiCommon.
169 #
170 def LoadGuidProtocolPpiCommon(XmlGuidProtocolPpiCommon):
171 GuidProtocolPpiCommon = GuidProtocolPpiCommonClass()
172
173 XmlTag = "Name"
174 GuidProtocolPpiCommon.Name = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag)
175
176 XmlParent = XmlNodeName(XmlGuidProtocolPpiCommon)
177 if XmlParent == "Entry":
178 XmlTag = "%s/C_Name" % XmlParent
179 elif XmlParent == "GuidCNames":
180 XmlTag = "%s/GuidCName" % XmlParent
181 else:
182 XmlTag = "%s/%sCName" % (XmlParent, XmlParent)
183
184 GuidProtocolPpiCommon.CName = XmlElement(XmlGuidProtocolPpiCommon, XmlTag)
185
186 XmlTag = XmlParent + "/" + "GuidValue"
187 GuidProtocolPpiCommon.Guid = XmlElement(XmlGuidProtocolPpiCommon, XmlTag)
188
189 if XmlParent.endswith("Notify"):
190 GuidProtocolPpiCommon.Notify = True
191
192 XmlTag = "GuidTypeList"
193 GuidTypes = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag)
194 GuidProtocolPpiCommon.GuidTypeList = GuidTypes.split()
195
196 XmlTag = "SupModuleList"
197 SupModules = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag)
198 GuidProtocolPpiCommon.SupModuleList = SupModules.split()
199
200 SetCommon(GuidProtocolPpiCommon, XmlGuidProtocolPpiCommon)
201
202 return GuidProtocolPpiCommon
203
204
205 ## Load a new Pcd class object.
206 #
207 # Read an input XML Pcd DOM object and return an object of Pcd
208 # contained in the DOM object.
209 #
210 # @param XmlPcd A child XML DOM object in a Common XML DOM.
211 #
212 # @retvel Pcd A new Pcd object created by XmlPcd.
213 #
214 def LoadPcd(XmlPcd):
215 """Return a new PcdClass object equivalent to XmlPcd"""
216 Pcd = PcdClass()
217
218 XmlTag = "PcdEntry/C_Name"
219 Pcd.CName = XmlElement(XmlPcd, XmlTag)
220
221 XmlTag = "PcdEntry/Token"
222 Pcd.Token = XmlElement(XmlPcd, XmlTag)
223
224 XmlTag = "PcdEntry/TokenSpaceGuidCName"
225 Pcd.TokenSpaceGuidCName = XmlElement(XmlPcd, XmlTag)
226
227 XmlTag = "PcdEntry/DatumType"
228 Pcd.DatumType = XmlElement(XmlPcd, XmlTag)
229
230 XmlTag = "PcdEntry/MaxDatumSize"
231 Pcd.MaxDatumSize = XmlElement(XmlPcd, XmlTag)
232
233 XmlTag = "PcdEntry/DefaultValue"
234 Pcd.DefaultValue = XmlElement(XmlPcd, XmlTag)
235
236 XmlTag = "PcdItemType"
237 Pcd.ItemType = XmlAttribute(XmlPcd, XmlTag)
238
239 XmlTag = "PcdEntry/ValidUsage"
240 Pcd.ValidUsage = XmlElement(XmlPcd, XmlTag).split()
241
242 XmlTag = "SupModuleList"
243 Pcd.SupModuleList = XmlAttribute(XmlPcd, XmlTag).split()
244
245 SetCommon(Pcd, XmlPcd)
246
247 return Pcd
248
249
250 ## Load a new LibraryClass class object.
251 #
252 # Read an input XML LibraryClass DOM object and return an object of LibraryClass
253 # contained in the DOM object.
254 #
255 # @param XmlLibraryClass A child XML DOM object in a Common XML DOM.
256 #
257 # @retvel LibraryClass A new LibraryClass object created by XmlLibraryClass.
258 #
259 def LoadLibraryClass(XmlLibraryClass):
260 LibraryClass = LibraryClassClass()
261
262 XmlTag = "LibraryClass/Keyword"
263 LibraryClass.LibraryClass = XmlElement(XmlLibraryClass, XmlTag)
264 if LibraryClass.LibraryClass == "":
265 XmlTag = "Name"
266 LibraryClass.LibraryClass = XmlAttribute(XmlLibraryClass, XmlTag)
267
268 XmlTag = "LibraryClass/IncludeHeader"
269 LibraryClass.IncludeHeader = XmlElement(XmlLibraryClass, XmlTag)
270
271 XmlTag = "RecommendedInstanceVersion"
272 RecommendedInstanceVersion = XmlAttribute(XmlLibraryClass, XmlTag)
273 LibraryClass.RecommendedInstanceVersion = RecommendedInstanceVersion
274
275 XmlTag = "RecommendedInstanceGuid"
276 RecommendedInstanceGuid = XmlAttribute(XmlLibraryClass, XmlTag)
277 LibraryClass.RecommendedInstanceGuid = RecommendedInstanceGuid
278
279 XmlTag = "SupModuleList"
280 SupModules = XmlAttribute(XmlLibraryClass, XmlTag)
281 LibraryClass.SupModuleList = SupModules.split()
282
283 SetCommon(LibraryClass, XmlLibraryClass)
284
285 return LibraryClass
286
287
288 ## Load a new Build Option class object.
289 #
290 # Read an input XML BuildOption DOM object and return an object of Build Option
291 # contained in the DOM object.
292 #
293 # @param XmlBuildOption A child XML DOM object in a Common XML DOM.
294 #
295 # @retvel BuildOption A new Build Option object created by XmlBuildOption.
296 #
297 def LoadBuildOption(XmlBuildOption):
298 """Return a new BuildOptionClass object equivalent to XmlBuildOption"""
299 BuildOption = BuildOptionClass()
300
301 BuildOption.Option = XmlElementData(XmlBuildOption)
302
303 XmlTag = "BuildTargets"
304 BuildOption.BuildTargetList = XmlAttribute(XmlBuildOption, XmlTag).split()
305
306 XmlTag = "ToolChainFamily"
307 BuildOption.ToolChainFamily = XmlAttribute(XmlBuildOption, XmlTag)
308
309 XmlTag = "TagName"
310 BuildOption.TagName = XmlAttribute(XmlBuildOption, XmlTag)
311
312 XmlTag = "ToolCode"
313 BuildOption.ToolCode = XmlAttribute(XmlBuildOption, XmlTag)
314
315 XmlTag = "SupArchList"
316 BuildOption.SupArchList = XmlAttribute(XmlBuildOption, XmlTag).split()
317
318 return BuildOption
319
320
321 ## Load a new User Extensions class object.
322 #
323 # Read an input XML UserExtensions DOM object and return an object of User
324 # Extensions contained in the DOM object.
325 #
326 # @param XmlUserExtensions A child XML DOM object in a Common XML DOM.
327 #
328 # @retvel UserExtensions A new User Extensions object created by
329 # XmlUserExtensions.
330 #
331 def LoadUserExtensions(XmlUserExtensions):
332 UserExtensions = UserExtensionsClass()
333
334 XmlTag = "UserID"
335 UserExtensions.UserID = XmlAttribute(XmlUserExtensions, XmlTag)
336
337 XmlTag = "Identifier"
338 UserExtensions.Identifier = XmlAttribute(XmlUserExtensions, XmlTag)
339
340 UserExtensions.Content = XmlElementData(XmlUserExtensions)
341
342 return UserExtensions
343
344
345 ## Store content to a text file object.
346 #
347 # Write some text file content to a text file object. The contents may echo
348 # in screen in a verbose way.
349 #
350 # @param TextFile The text file object.
351 # @param Content The string object to be written to a text file.
352 #
353 def StoreTextFile(TextFile, Content):
354 EdkLogger.verbose(Content)
355 TextFile.write(Content)
356
357
358 ## Add item to a section.
359 #
360 # Add an Item with specific CPU architecture to section dictionary.
361 # The possible duplication is ensured to be removed.
362 #
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.
366 #
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
372
373
374 ## Get section contents.
375 #
376 # Return the content of section named SectionName.
377 # the contents is based on Methods and ObjectLists.
378 #
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.
382 #
383 # @retval Section The string content of a section.
384 #
385 def GetSection(SectionName, Method, ObjectList):
386 SupportedArches = ["common", "Ia32", "X64", "Ipf", "Ebc", "ARM", "AARCH64"]
387 SectionDict = {}
388 for Object in ObjectList:
389 Item = Method(Object)
390 if Item == "":
391 continue
392 Item = " %s" % Item
393 Arches = Object.SupArchList
394 if len(Arches) == 0:
395 AddToSection(SectionDict, "common", Item)
396 else:
397 for Arch in SupportedArches:
398 if Arch.upper() in Arches:
399 AddToSection(SectionDict, Arch, Item)
400
401 Section = ""
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)
406 Section += "\n"
407 if Section != "":
408 Section += "\n"
409 return Section
410
411
412 ## Store file header to a text file.
413 #
414 # Write standard file header to a text file. The content includes copyright,
415 # abstract, description and license extracted from CommonHeader class object.
416 #
417 # @param TextFile The text file object.
418 # @param CommonHeader The source CommonHeader class object.
419 #
420 def StoreHeader(TextFile, CommonHeader):
421 CopyRight = CommonHeader.Copyright
422 Abstract = CommonHeader.Abstract
423 Description = CommonHeader.Description
424 License = CommonHeader.License
425
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"
432
433 StoreTextFile(TextFile, Header)
434
435 ## Store file header to a text file.
436 #
437 # Write Defines section to a text file. DefinesTupleList determines the content.
438 #
439 # @param TextFile The text file object.
440 # @param DefinesTupleList The list of (Tag, Value) to be added as one item.
441 #
442 def StoreDefinesSection(TextFile, DefinesTupleList):
443 Section = "[Defines]\n"
444 for DefineItem in DefinesTupleList:
445 Section += " %-30s = %s\n" % DefineItem
446
447 Section += "\n\n"
448 StoreTextFile(TextFile, Section)
449
450
451 ## Return one User Extension section.
452 #
453 # Read the input UserExtentsions class object and return one section.
454 #
455 # @param UserExtensions An input UserExtensions class object.
456 #
457 # @retval UserExtensionSection A section representing UserExtensions object.
458 #
459 def GetUserExtensions(UserExtensions):
460 UserId = UserExtensions.UserID
461 Identifier = UserExtensions.Identifier
462 Content = UserExtensions.Content
463
464 return "[UserExtensions.%s.%s]\n %s\n\n" % (UserId, Identifier, Content)
465
466 ## Regular expression to match an equation.
467 mReEquation = re.compile(r"\s*(\S+)\s*=\s*(\S*)\s*")
468
469 ## Return a value tuple matching information in a text fle.
470 #
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.
473 #
474 # @param FileName The file name of the text file.
475 # @param TagTuple A tuple of tags as the key to the value.
476 #
477 # @param ValueTupe The returned tuple corresponding to the tag tuple.
478 #
479 def GetTextFileInfo(FileName, TagTuple):
480 ValueTuple = [""] * len(TagTuple)
481 try:
482 for Line in open(FileName):
483 Line = Line.split("#", 1)[0]
484 MatchEquation = mReEquation.match(Line)
485 if MatchEquation:
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
491 except:
492 EdkLogger.info("IO Error in reading file %s" % FileName)
493
494 return ValueTuple
495
496
497 ## Return a value tuple matching information in an XML fle.
498 #
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.
501 #
502 # @param FileName The file name of the XML file.
503 # @param TagTuple A tuple of tags as the key to the value.
504 #
505 # @param ValueTupe The returned tuple corresponding to the tag tuple.
506 #
507 def GetXmlFileInfo(FileName, TagTuple):
508 XmlDom = XmlParseFile(FileName)
509 return tuple([XmlElement(XmlDom, XmlTag) for XmlTag in TagTuple])
510
511
512 ## Parse migration command line options
513 #
514 # Use standard Python module optparse to parse command line option of this tool.
515 #
516 # @param Source The source file type.
517 # @param Destinate The destinate file type.
518 #
519 # @retval Options A optparse object containing the parsed options.
520 # @retval InputFile Path of an source file to be migrated.
521 #
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."
527
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.")
533
534 Options, Args = Parser.parse_args()
535
536 # Set logging level
537 if Options.verbose:
538 EdkLogger.setLevel(EdkLogger.VERBOSE)
539 elif Options.quiet:
540 EdkLogger.setLevel(EdkLogger.QUIET)
541 else:
542 EdkLogger.setLevel(EdkLogger.INFO)
543
544 # error check
545 if len(Args) == 0:
546 raise MigrationError(PARAMETER_MISSING, name="Input file", usage=Parser.get_usage())
547 if len(Args) > 1:
548 raise MigrationError(PARAMETER_INVALID, name="Too many input files", usage=Parser.get_usage())
549
550 InputFile = Args[0]
551 if not os.path.exists(InputFile):
552 raise MigrationError(FILE_NOT_FOUND, name=InputFile)
553
554 if Options.OutputFile:
555 if Options.AutoWrite:
556 raise MigrationError(OPTION_CONFLICT, arg1="-o", arg2="-a", usage=Parser.get_usage())
557 else:
558 if Options.AutoWrite:
559 Options.OutputFile = os.path.splitext(InputFile)[0] + "." + Destinate.lower()
560 else:
561 raise MigrationError(OPTION_MISSING, name="-o", usage=Parser.get_usage())
562
563 return Options, InputFile
564
565 # This acts like the main() function for the script, unless it is 'import'ed
566 # into another script.
567 if __name__ == '__main__':
568 pass