Home | History | Annotate | Download | only in PomAdapter
      1 ## @file DecPomAlignment.py

      2 # This file contained the adapter for convert INF parser object to POM Object

      3 #

      4 # Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>

      5 #

      6 # This program and the accompanying materials are licensed and made available 

      7 # under the terms and conditions of the BSD License which accompanies this 

      8 # distribution. The full text of the license may be found at 

      9 # http://opensource.org/licenses/bsd-license.php

     10 #

     11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     13 #

     14 
     15 '''
     16 DecPomAlignment
     17 '''
     18 
     19 ##

     20 # Import Modules

     21 #

     22 import os.path
     23 from os import sep
     24 import platform
     25 
     26 import re
     27 import Logger.Log as Logger
     28 from Logger import StringTable as ST
     29 from Logger.ToolError import UPT_MUL_DEC_ERROR
     30 from Logger.ToolError import FORMAT_INVALID
     31 
     32 from Library.Parsing import NormPath
     33 from Library.DataType import ARCH_LIST
     34 from Library.DataType import TAB_GUIDS
     35 from Library.DataType import TAB_PROTOCOLS
     36 from Library.DataType import TAB_PPIS
     37 from Library.DataType import TAB_DEC_DEFINES_PACKAGE_NAME
     38 from Library.DataType import TAB_DEC_DEFINES_PACKAGE_GUID
     39 from Library.DataType import TAB_DEC_DEFINES_PACKAGE_VERSION
     40 from Library.DataType import TAB_DEC_DEFINES_DEC_SPECIFICATION
     41 from Library.DataType import TAB_DEC_DEFINES_PKG_UNI_FILE
     42 from Library.DataType import TAB_ARCH_COMMON
     43 from Library.DataType import TAB_INCLUDES
     44 from Library.DataType import TAB_LIBRARY_CLASSES
     45 from Library.DataType import TAB_PCDS
     46 from Library.DataType import TAB_PCDS_FIXED_AT_BUILD_NULL
     47 from Library.DataType import TAB_PCDS_PATCHABLE_IN_MODULE_NULL
     48 from Library.DataType import TAB_PCDS_FEATURE_FLAG_NULL
     49 from Library.DataType import TAB_PCDS_DYNAMIC_EX_NULL
     50 from Library.DataType import TAB_PCDS_DYNAMIC_NULL
     51 from Library.DataType import TAB_PTR_TYPE_PCD
     52 from Library.DataType import ITEM_UNDEFINED
     53 from Library.DataType import TAB_DEC_BINARY_ABSTRACT
     54 from Library.DataType import TAB_DEC_BINARY_DESCRIPTION
     55 from Library.DataType import TAB_LANGUAGE_EN_US
     56 from Library.DataType import TAB_BINARY_HEADER_IDENTIFIER
     57 from Library.DataType import TAB_BINARY_HEADER_USERID
     58 from Library.DataType import TAB_LANGUAGE_EN_X
     59 from Library.DataType import TAB_LANGUAGE_EN
     60 from Library.DataType import TAB_STR_TOKENCNAME
     61 from Library.DataType import TAB_STR_TOKENPROMPT
     62 from Library.DataType import TAB_STR_TOKENHELP
     63 from Library.DataType import TAB_STR_TOKENERR
     64 from Library.DataType import TAB_HEX_START
     65 from Library.DataType import TAB_SPLIT
     66 import Library.DataType as DT
     67 from Library.CommentParsing import ParseHeaderCommentSection
     68 from Library.CommentParsing import ParseGenericComment
     69 from Library.CommentParsing import ParseDecPcdGenericComment
     70 from Library.CommentParsing import ParseDecPcdTailComment
     71 from Library.Misc import GetFiles
     72 from Library.Misc import Sdict
     73 from Library.Misc import GetRelativePath
     74 from Library.Misc import PathClass
     75 from Library.Misc import ValidateUNIFilePath
     76 from Library.UniClassObject import UniFileClassObject
     77 from Library.UniClassObject import ConvertSpecialUnicodes
     78 from Library.UniClassObject import GetLanguageCode1766
     79 from Library.ParserValidate import IsValidPath
     80 from Parser.DecParser import Dec
     81 from Object.POM.PackageObject import PackageObject
     82 from Object.POM.CommonObject import UserExtensionObject
     83 from Object.POM.CommonObject import IncludeObject
     84 from Object.POM.CommonObject import GuidObject
     85 from Object.POM.CommonObject import ProtocolObject
     86 from Object.POM.CommonObject import PpiObject
     87 from Object.POM.CommonObject import LibraryClassObject
     88 from Object.POM.CommonObject import PcdObject
     89 from Object.POM.CommonObject import TextObject
     90 from Object.POM.CommonObject import MiscFileObject
     91 from Object.POM.CommonObject import FileObject
     92 
     93 
     94 ## DecPomAlignment

     95 #

     96 # Inherited from PackageObject

     97 #

     98 class DecPomAlignment(PackageObject):
     99     def __init__(self, Filename, WorkspaceDir = None, CheckMulDec = False):
    100         PackageObject.__init__(self)
    101         self.UserExtensions = ''
    102         self.WorkspaceDir = WorkspaceDir
    103         self.SupArchList = ARCH_LIST
    104         self.CheckMulDec = CheckMulDec
    105         self.DecParser = None
    106         self.UniFileClassObject = None
    107         self.PcdDefaultValueDict = {}
    108         
    109         #

    110         # Load Dec file

    111         #

    112         self.LoadDecFile(Filename)
    113         
    114         #

    115         # Transfer to Package Object if IsToPackage is True

    116         #

    117         self.DecToPackage()
    118     
    119     ## Load Dec file

    120     #

    121     # Load the file if it exists

    122     #

    123     # @param Filename:  Input value for filename of Dec file

    124     #

    125     def LoadDecFile(self, Filename):
    126         #

    127         # Insert a record for file

    128         #

    129         Filename = NormPath(Filename)
    130         (Path, Name) = os.path.split(Filename)
    131         self.SetFullPath(Filename)
    132         self.SetRelaPath(Path)
    133         self.SetFileName(Name)
    134         self.SetPackagePath(GetRelativePath(Path, self.WorkspaceDir))   
    135         self.SetCombinePath(GetRelativePath(Filename, self.WorkspaceDir))
    136         
    137         self.DecParser = Dec(Filename)
    138     
    139     ## Transfer to Package Object

    140     # 

    141     # Transfer all contents of a Dec file to a standard Package Object

    142     #

    143     def DecToPackage(self):
    144         #

    145         # Init global information for the file

    146         #

    147         ContainerFile = self.GetFullPath()
    148         
    149         #

    150         # Generate Package Header

    151         #

    152         self.GenPackageHeader(ContainerFile)
    153         
    154         #

    155         # Generate Includes

    156         #

    157         self.GenIncludes(ContainerFile)
    158 
    159         #

    160         # Generate Guids

    161         #

    162         self.GenGuidProtocolPpis(TAB_GUIDS, ContainerFile)
    163 
    164         #

    165         # Generate Protocols

    166         #

    167         self.GenGuidProtocolPpis(TAB_PROTOCOLS, ContainerFile)
    168 
    169         #

    170         # Generate Ppis

    171         #

    172         self.GenGuidProtocolPpis(TAB_PPIS, ContainerFile)
    173         
    174         #

    175         # Generate LibraryClasses

    176         #

    177         self.GenLibraryClasses(ContainerFile)
    178         
    179         #

    180         # Generate Pcds

    181         #

    182         self.GenPcds(ContainerFile)
    183         
    184         #

    185         # Generate Module File list, will be used later on to generate 

    186         # distribution

    187         #

    188         self.GenModuleFileList(ContainerFile)
    189         
    190         #

    191         # Generate user extensions

    192         #

    193         self.GenUserExtensions()
    194         
    195     ## Generate user extension

    196     #

    197     #

    198     def GenUserExtensions(self):
    199         UEObj = self.DecParser.GetUserExtensionSectionObject()
    200         UEList = UEObj.GetAllUserExtensions()
    201         for Item in UEList:
    202             if not Item.UserString:
    203                 continue
    204             UserExtension = UserExtensionObject()
    205             UserId = Item.UserId
    206             if UserId.startswith('"') and UserId.endswith('"'):
    207                 UserId = UserId[1:-1]
    208             UserExtension.SetUserID(UserId)
    209             Identifier = Item.IdString
    210             if Identifier.startswith('"') and Identifier.endswith('"'):
    211                 Identifier = Identifier[1:-1]
    212             #

    213             # Generate miscellaneous files of DEC file

    214             #

    215             if UserId == 'TianoCore' and Identifier == 'ExtraFiles':
    216                 self.GenMiscFiles(Item.UserString)
    217             UserExtension.SetIdentifier(Identifier)
    218             UserExtension.SetStatement(Item.UserString)
    219             UserExtension.SetSupArchList(
    220                 Item.ArchAndModuleType
    221             )
    222             self.SetUserExtensionList(
    223                 self.GetUserExtensionList() + [UserExtension]
    224             )
    225 
    226         # Add Private sections to UserExtension

    227         if self.DecParser.GetPrivateSections():
    228             PrivateUserExtension = UserExtensionObject()
    229             PrivateUserExtension.SetStatement(self.DecParser.GetPrivateSections())
    230             PrivateUserExtension.SetIdentifier(DT.TAB_PRIVATE)
    231             PrivateUserExtension.SetUserID(DT.TAB_INTEL)
    232             self.SetUserExtensionList(self.GetUserExtensionList() + [PrivateUserExtension])
    233             
    234     ## Generate miscellaneous files on DEC file

    235     #

    236     #

    237     def GenMiscFiles(self, Content):
    238         MiscFileObj = MiscFileObject()
    239         for Line in Content.splitlines():
    240             FileName = ''
    241             if '#' in Line:
    242                 FileName = Line[:Line.find('#')]
    243             else:
    244                 FileName = Line
    245             if FileName:
    246                 if IsValidPath(FileName, self.GetRelaPath()):
    247                     FileObj = FileObject()
    248                     FileObj.SetURI(FileName)
    249                     MiscFileObj.SetFileList(MiscFileObj.GetFileList()+[FileObj])
    250                 else:
    251                     Logger.Error("InfParser", 
    252                                  FORMAT_INVALID,
    253                                  ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(Line),
    254                                  File=self.GetFileName(),
    255                                  ExtraData=Line)   
    256         self.SetMiscFileList(self.GetMiscFileList()+[MiscFileObj]) 
    257         
    258     ## Generate Package Header

    259     #

    260     # Gen Package Header of Dec as <Key> = <Value>

    261     #

    262     # @param ContainerFile: The Dec file full path 

    263     #

    264     def GenPackageHeader(self, ContainerFile):
    265         Logger.Debug(2, "Generate PackageHeader ...")
    266         DefinesDict = {}
    267         
    268         #

    269         # Update all defines item in database

    270         #

    271         DefObj = self.DecParser.GetDefineSectionObject()
    272         for Item in DefObj.GetDefines():
    273             #

    274             # put items into Dict except for PackageName, Guid, Version, DEC_SPECIFICATION

    275             #

    276             SkipItemList = [TAB_DEC_DEFINES_PACKAGE_NAME, \
    277                 TAB_DEC_DEFINES_PACKAGE_GUID, TAB_DEC_DEFINES_PACKAGE_VERSION, \
    278                 TAB_DEC_DEFINES_DEC_SPECIFICATION, TAB_DEC_DEFINES_PKG_UNI_FILE]
    279             if Item.Key in SkipItemList:
    280                 continue
    281             DefinesDict['%s = %s' % (Item.Key, Item.Value)] = TAB_ARCH_COMMON
    282 
    283         self.SetBaseName(DefObj.GetPackageName())
    284         self.SetVersion(DefObj.GetPackageVersion())
    285 #        self.SetName(DefObj.GetPackageName() + ' Version ' + \

    286 #                     DefObj.GetPackageVersion())

    287         self.SetName(os.path.splitext(self.GetFileName())[0])
    288         self.SetGuid(DefObj.GetPackageGuid())
    289         if DefObj.GetPackageUniFile():
    290             ValidateUNIFilePath(DefObj.GetPackageUniFile())
    291             self.UniFileClassObject = \
    292             UniFileClassObject([PathClass(os.path.join(DefObj.GetPackagePath(), DefObj.GetPackageUniFile()))])
    293         else:
    294             self.UniFileClassObject = None
    295      
    296         if DefinesDict:
    297             UserExtension = UserExtensionObject()
    298             UserExtension.SetDefinesDict(DefinesDict)
    299             UserExtension.SetIdentifier('DefineModifiers')
    300             UserExtension.SetUserID('EDK2')  
    301             self.SetUserExtensionList(
    302                 self.GetUserExtensionList() + [UserExtension]
    303             )
    304 
    305         #

    306         # Get File header information

    307         #

    308         if self.UniFileClassObject:
    309             Lang = TAB_LANGUAGE_EN_X
    310         else:
    311             Lang = TAB_LANGUAGE_EN_US
    312         Abstract, Description, Copyright, License = \
    313             ParseHeaderCommentSection(self.DecParser.GetHeadComment(),
    314                                       ContainerFile)
    315         if Abstract:
    316             self.SetAbstract((Lang, Abstract))
    317         if Description:
    318             self.SetDescription((Lang, Description))
    319         if Copyright:
    320             self.SetCopyright(('', Copyright))
    321         if License:
    322             self.SetLicense(('', License))
    323     
    324         #

    325         # Get Binary header information

    326         #

    327         if self.DecParser.BinaryHeadComment:
    328             Abstract, Description, Copyright, License = \
    329                 ParseHeaderCommentSection(self.DecParser.BinaryHeadComment,
    330                                       ContainerFile, True)
    331                 
    332             if not Abstract  or not Description or not Copyright or not License:
    333                 Logger.Error('MkPkg',
    334                              FORMAT_INVALID,
    335                              ST.ERR_INVALID_BINARYHEADER_FORMAT,
    336                              ContainerFile)
    337             else:
    338                 self.SetBinaryHeaderAbstract((Lang, Abstract))
    339                 self.SetBinaryHeaderDescription((Lang, Description))
    340                 self.SetBinaryHeaderCopyright(('', Copyright))
    341                 self.SetBinaryHeaderLicense(('', License))
    342 
    343         BinaryAbstractList = []
    344         BinaryDescriptionList = []
    345         
    346         #Get Binary header from UNI file

    347         # Initialize the UniStrDict dictionary, top keys are language codes

    348         UniStrDict = {}
    349         if self.UniFileClassObject:
    350             UniStrDict = self.UniFileClassObject.OrderedStringList
    351             for Lang in UniStrDict:
    352                 for StringDefClassObject in UniStrDict[Lang]:
    353                     Lang = GetLanguageCode1766(Lang)
    354                     if StringDefClassObject.StringName == TAB_DEC_BINARY_ABSTRACT:
    355                         if (Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue)) \
    356                         not in self.GetBinaryHeaderAbstract():
    357                             BinaryAbstractList.append((Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue)))
    358                     if StringDefClassObject.StringName == TAB_DEC_BINARY_DESCRIPTION:
    359                         if (Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue)) \
    360                         not in self.GetBinaryHeaderDescription():
    361                             BinaryDescriptionList.append((Lang, 
    362                                                           ConvertSpecialUnicodes(StringDefClassObject.StringValue)))
    363         #Combine Binary header from DEC file and UNI file

    364         BinaryAbstractList = self.GetBinaryHeaderAbstract() + BinaryAbstractList
    365         BinaryDescriptionList = self.GetBinaryHeaderDescription() + BinaryDescriptionList
    366         BinaryCopyrightList = self.GetBinaryHeaderCopyright()
    367         BinaryLicenseList = self.GetBinaryHeaderLicense()
    368         #Generate the UserExtensionObject for TianoCore."BinaryHeader"

    369         if BinaryAbstractList or BinaryDescriptionList or BinaryCopyrightList or BinaryLicenseList:
    370             BinaryUserExtension = UserExtensionObject()
    371             BinaryUserExtension.SetBinaryAbstract(BinaryAbstractList)
    372             BinaryUserExtension.SetBinaryDescription(BinaryDescriptionList)
    373             BinaryUserExtension.SetBinaryCopyright(BinaryCopyrightList)
    374             BinaryUserExtension.SetBinaryLicense(BinaryLicenseList)
    375             BinaryUserExtension.SetIdentifier(TAB_BINARY_HEADER_IDENTIFIER)
    376             BinaryUserExtension.SetUserID(TAB_BINARY_HEADER_USERID)
    377             self.SetUserExtensionList(self.GetUserExtensionList() + [BinaryUserExtension])
    378             
    379             
    380     ## GenIncludes

    381     #

    382     # Gen Includes of Dec

    383     # 

    384     # @param ContainerFile: The Dec file full path 

    385     #

    386     def GenIncludes(self, ContainerFile):
    387         if ContainerFile:
    388             pass
    389         Logger.Debug(2, "Generate %s ..." % TAB_INCLUDES)
    390         IncludesDict = Sdict()
    391 
    392         IncObj = self.DecParser.GetIncludeSectionObject()
    393         for Item in IncObj.GetAllIncludes():
    394             IncludePath = os.path.normpath(Item.File)
    395             if platform.system() != 'Windows' and platform.system() != 'Microsoft':
    396                 IncludePath = IncludePath.replace('\\', '/')
    397             if IncludePath in IncludesDict:
    398                 if Item.GetArchList() == [TAB_ARCH_COMMON] or IncludesDict[IncludePath] == [TAB_ARCH_COMMON]:
    399                     IncludesDict[IncludePath] = [TAB_ARCH_COMMON]
    400                 else:
    401                     IncludesDict[IncludePath] = IncludesDict[IncludePath] + Item.GetArchList()
    402             else:
    403                 IncludesDict[IncludePath] = Item.GetArchList()
    404                         
    405         # 
    406         # get the  standardIncludeFileList(industry), packageIncludeFileList
    407         # (others) for PackageObject  
    408         # 
    409         PackagePath = os.path.split(self.GetFullPath())[0]
    410         IncludePathList = \
    411             [os.path.normpath(Path) + sep for Path in IncludesDict.keys()]
    412         IncludePathList.sort()
    413         
    414         #
    415         # get a non-overlap set of include path, IncludePathList should be 
    416         # sorted, and path should be end with path seperator '\'
    417         #
    418         NonOverLapList = []
    419         for Path1 in IncludePathList:
    420             for Path2 in NonOverLapList:
    421                 if Path1.startswith(Path2):
    422                     break
    423             else:
    424                 NonOverLapList.append(Path1)
    425         #
    426         # revert the list so the longest path shown first in list, also need
    427         # to remove the extra path seperator '\'
    428         # as this list is used to search the supported Arch info
    429         #
    430         for IndexN in range (0, len(IncludePathList)):
    431             IncludePathList[IndexN] = os.path.normpath(IncludePathList[IndexN])
    432         IncludePathList.sort()            
    433         IncludePathList.reverse()
    434         #
    435         # save the include path list for later usage
    436         #
    437         self.SetIncludePathList(IncludePathList)
    438         StandardIncludeFileList = []
    439         PackageIncludeFileList = []
    440         
    441         IncludeFileList = []
    442         for Path in NonOverLapList:
    443             FileList = GetFiles(os.path.join(PackagePath, Path), ['CVS', '.svn'], False)
    444             IncludeFileList += [os.path.normpath(os.path.join(Path, File)) for File in FileList]
    445         for Includefile in IncludeFileList:
    446             ExtName = os.path.splitext(Includefile)[1]
    447             if ExtName.upper() == '.DEC' and self.CheckMulDec:
    448                 Logger.Error('MkPkg', 
    449                              UPT_MUL_DEC_ERROR,
    450                              ST.ERR_MUL_DEC_ERROR%(os.path.dirname(ContainerFile), 
    451                                                    os.path.basename(ContainerFile),
    452                                                    Includefile))
    453 
    454             FileCombinePath = os.path.dirname(Includefile)
    455             Include = IncludeObject()
    456             for Path in IncludePathList:
    457                 if FileCombinePath.startswith(Path):
    458                     SupArchList = IncludesDict[Path]
    459                     break
    460             Include.SetFilePath(Includefile)
    461             Include.SetSupArchList(SupArchList)
    462             if Includefile.find('IndustryStandard') != -1:
    463                 StandardIncludeFileList.append(Include)
    464             else:
    465                 PackageIncludeFileList.append(Include)            
    466     
    467         self.SetStandardIncludeFileList(StandardIncludeFileList)
    468 
    469         #
    470         # put include path into the PackageIncludeFileList
    471         #
    472         PackagePathList = []
    473         IncObj = self.DecParser.GetIncludeSectionObject()        
    474         for Item in IncObj.GetAllIncludes():
    475             IncludePath = Item.File
    476             Include = IncludeObject()
    477             Include.SetFilePath(IncludePath)
    478             Include.SetSupArchList(Item.GetArchList())
    479             PackagePathList.append(Include)
    480         self.SetPackageIncludeFileList(PackagePathList + PackageIncludeFileList)
    481     
    482     ## GenPpis
    483     #
    484     # Gen Ppis of Dec
    485     # <CName>=<GuidValue>
    486     #
    487     # @param ContainerFile: The Dec file full path 
    488     #
    489     def GenGuidProtocolPpis(self, Type, ContainerFile):
    490         if ContainerFile:
    491             pass
    492         Logger.Debug(2, "Generate %s ..." % Type)
    493 
    494         Obj = None
    495         Factory = None
    496         if Type == TAB_GUIDS:
    497             Obj = self.DecParser.GetGuidSectionObject()
    498             def CreateGuidObject():
    499                 Object = GuidObject()
    500                 Object.SetGuidTypeList([])
    501                 Object.SetUsage(None)
    502                 Object.SetName(None)
    503                 return Object
    504             Factory = CreateGuidObject
    505         elif Type == TAB_PROTOCOLS:
    506             Obj = self.DecParser.GetProtocolSectionObject()
    507             
    508             def CreateProtocolObject():
    509                 return ProtocolObject()
    510             Factory = CreateProtocolObject
    511         elif Type == TAB_PPIS:
    512             Obj = self.DecParser.GetPpiSectionObject()
    513 
    514             def CreatePpiObject():
    515                 return PpiObject()
    516             Factory = CreatePpiObject
    517         else:
    518             #
    519             # Should not be here
    520             #
    521             return
    522         
    523         DeclarationsList = []
    524         
    525         #
    526         # Go through each arch
    527         #
    528         for Item in Obj.GetGuidStyleAllItems():
    529             Name = Item.GuidCName
    530             Value = Item.GuidString
    531             HelpTxt = ParseGenericComment(Item.GetHeadComment() + \
    532                                           Item.GetTailComment())
    533             
    534             ListObject = Factory()
    535             ListObject.SetCName(Name)
    536             ListObject.SetGuid(Value)
    537             ListObject.SetSupArchList(Item.GetArchList())
    538             if HelpTxt:
    539                 if self.UniFileClassObject:
    540                     HelpTxt.SetLang(TAB_LANGUAGE_EN_X)
    541                 ListObject.SetHelpTextList([HelpTxt])
    542             
    543             DeclarationsList.append(ListObject)
    544 
    545         #    
    546         #GuidTypeList is abstracted from help
    547         #
    548         if Type == TAB_GUIDS:
    549             self.SetGuidList(self.GetGuidList() + DeclarationsList)
    550         elif Type == TAB_PROTOCOLS:
    551             self.SetProtocolList(self.GetProtocolList() + DeclarationsList)
    552         elif Type == TAB_PPIS:
    553             self.SetPpiList(self.GetPpiList() + DeclarationsList)
    554     
    555     ## GenLibraryClasses
    556     #
    557     # Gen LibraryClasses of Dec
    558     # <CName>=<GuidValue>
    559     #
    560     # @param ContainerFile: The Dec file full path 
    561     #
    562     def GenLibraryClasses(self, ContainerFile):
    563         if ContainerFile:
    564             pass
    565         Logger.Debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES)
    566         LibraryClassDeclarations = []
    567         
    568         LibObj = self.DecParser.GetLibraryClassSectionObject()
    569         for Item in LibObj.GetAllLibraryclasses():
    570             LibraryClass = LibraryClassObject()
    571             LibraryClass.SetLibraryClass(Item.Libraryclass)
    572             LibraryClass.SetSupArchList(Item.GetArchList())
    573             LibraryClass.SetIncludeHeader(Item.File)
    574             HelpTxt = ParseGenericComment(Item.GetHeadComment() + \
    575                                           Item.GetTailComment(), None, '@libraryclass')
    576             if HelpTxt:
    577                 if self.UniFileClassObject:
    578                     HelpTxt.SetLang(TAB_LANGUAGE_EN_X)
    579                 LibraryClass.SetHelpTextList([HelpTxt])
    580             LibraryClassDeclarations.append(LibraryClass)
    581         
    582         self.SetLibraryClassList(self.GetLibraryClassList() + \
    583                                  LibraryClassDeclarations)
    584     
    585     ## GenPcds
    586     #
    587     # Gen Pcds of Dec
    588     # <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
    589     #
    590     # @param ContainerFile: The Dec file full path 
    591     #
    592     def GenPcds(self, ContainerFile):
    593         Logger.Debug(2, "Generate %s ..." % TAB_PCDS)
    594         PcdObj = self.DecParser.GetPcdSectionObject()
    595         #
    596         # Get all Pcds
    597         #        
    598         PcdDeclarations = []
    599         IterList = [
    600             (TAB_PCDS_FIXED_AT_BUILD_NULL,      'FixedPcd'),
    601             (TAB_PCDS_PATCHABLE_IN_MODULE_NULL, 'PatchPcd'), 
    602             (TAB_PCDS_FEATURE_FLAG_NULL,        'FeaturePcd'),
    603             (TAB_PCDS_DYNAMIC_EX_NULL,          'PcdEx'), 
    604             (TAB_PCDS_DYNAMIC_NULL,             'Pcd')]
    605         
    606         PromptStrList = []
    607         HelpStrList = []
    608         PcdErrStrList = []
    609         # Initialize UniStrDict dictionary, top keys are language codes
    610         UniStrDict = {}
    611         StrList = []
    612         
    613         Language = ''
    614         if self.UniFileClassObject:
    615             Language = TAB_LANGUAGE_EN_X
    616         else:
    617             Language = TAB_LANGUAGE_EN_US
    618             
    619         if self.UniFileClassObject:
    620             UniStrDict = self.UniFileClassObject.OrderedStringList
    621             for Lang in UniStrDict:
    622                 for StringDefClassObject in UniStrDict[Lang]:
    623                     StrList = StringDefClassObject.StringName.split('_')
    624                     # StringName format is STR_<TOKENSPACECNAME>_<PCDCNAME>_PROMPT
    625                     if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[3] == TAB_STR_TOKENPROMPT:
    626                         PromptStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \
    627                                               StringDefClassObject.StringValue))
    628                     # StringName format is STR_<TOKENSPACECNAME>_<PCDCNAME>_HELP
    629                     if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[3] == TAB_STR_TOKENHELP:
    630                         HelpStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \
    631                                             StringDefClassObject.StringValue))
    632                     # StringName format is STR_<TOKENSPACECNAME>_ERR_##
    633                     if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[2] == TAB_STR_TOKENERR:
    634                         PcdErrStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \
    635                                               StringDefClassObject.StringValue))
    636         #
    637         # For each PCD type
    638         #
    639         for PcdType, Type in IterList:
    640             #
    641             # Go through all archs
    642             #
    643             # for Arch in self.SupArchList + [TAB_ARCH_COMMON]:
    644             #
    645             for Item in PcdObj.GetPcdsByType(PcdType.upper()):
    646                 PcdDeclaration = GenPcdDeclaration(
    647                         ContainerFile,
    648                         (Item.TokenSpaceGuidCName, Item.TokenCName,
    649                         Item.DefaultValue, Item.DatumType, Item.TokenValue,
    650                         Type, Item.GetHeadComment(), Item.GetTailComment(),''),
    651                         Language,
    652                         self.DecParser.GetDefineSectionMacro()
    653                         )
    654                 PcdDeclaration.SetSupArchList(Item.GetArchListOfType(PcdType))
    655                 
    656                 #
    657                 # Get PCD error message from PCD error comment section in DEC file
    658                 #
    659                 for PcdErr in PcdDeclaration.GetPcdErrorsList():
    660                     if (PcdDeclaration.GetTokenSpaceGuidCName(), PcdErr.GetErrorNumber()) \
    661                         in self.DecParser.PcdErrorCommentDict:
    662                         Key = (PcdDeclaration.GetTokenSpaceGuidCName(), PcdErr.GetErrorNumber())
    663                         PcdErr.SetErrorMessageList(PcdErr.GetErrorMessageList() + \
    664                                                       [(Language, self.DecParser.PcdErrorCommentDict[Key])])
    665                 
    666                 for Index in range(0, len(PromptStrList)):
    667                     StrNameList = PromptStrList[Index][1].split('_')
    668                     if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \
    669                     StrNameList[2].lower() == Item.TokenCName.lower():
    670                         TxtObj = TextObject()
    671                         TxtObj.SetLang(PromptStrList[Index][0])
    672                         TxtObj.SetString(PromptStrList[Index][2])
    673                         for Prompt in PcdDeclaration.GetPromptList():
    674                             if Prompt.GetLang() == TxtObj.GetLang() and \
    675                                 Prompt.GetString() == TxtObj.GetString():
    676                                 break
    677                         else:
    678                             PcdDeclaration.SetPromptList(PcdDeclaration.GetPromptList() + [TxtObj])
    679                         
    680                 for Index in range(0, len(HelpStrList)):
    681                     StrNameList = HelpStrList[Index][1].split('_')
    682                     if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \
    683                     StrNameList[2].lower() == Item.TokenCName.lower():
    684                         TxtObj = TextObject()
    685                         TxtObj.SetLang(HelpStrList[Index][0])
    686                         TxtObj.SetString(HelpStrList[Index][2])
    687                         for HelpStrObj in PcdDeclaration.GetHelpTextList():
    688                             if HelpStrObj.GetLang() == TxtObj.GetLang() and \
    689                                 HelpStrObj.GetString() == TxtObj.GetString():
    690                                 break
    691                         else:
    692                             PcdDeclaration.SetHelpTextList(PcdDeclaration.GetHelpTextList() + [TxtObj])
    693 
    694                 #
    695                 # Get PCD error message from UNI file
    696                 #
    697                 for Index in range(0, len(PcdErrStrList)):
    698                     StrNameList = PcdErrStrList[Index][1].split('_')
    699                     if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \
    700                         StrNameList[2].lower() == TAB_STR_TOKENERR.lower():
    701                         for PcdErr in PcdDeclaration.GetPcdErrorsList():
    702                             if PcdErr.GetErrorNumber().lower() == (TAB_HEX_START + StrNameList[3]).lower() and \
    703                                 (PcdErrStrList[Index][0], PcdErrStrList[Index][2]) not in PcdErr.GetErrorMessageList():
    704                                 PcdErr.SetErrorMessageList(PcdErr.GetErrorMessageList() + \
    705                                                             [(PcdErrStrList[Index][0], PcdErrStrList[Index][2])])
    706                               
    707                 #
    708                 # Check to prevent missing error message if a Pcd has the error code.
    709                 #
    710                 for PcdErr in PcdDeclaration.GetPcdErrorsList():
    711                     if PcdErr.GetErrorNumber().strip():
    712                         if not PcdErr.GetErrorMessageList():
    713                             Logger.Error('UPT',
    714                                          FORMAT_INVALID,
    715                                          ST.ERR_DECPARSE_PCD_UNMATCHED_ERRORCODE % PcdErr.GetErrorNumber(),
    716                                          ContainerFile,
    717                                          PcdErr.GetLineNum(),
    718                                          PcdErr.GetFileLine())                        
    719                     
    720                 PcdDeclarations.append(PcdDeclaration)
    721         self.SetPcdList(self.GetPcdList() + PcdDeclarations)
    722         self.CheckPcdValue()
    723         
    724     ##
    725     # Get error message via language
    726     # @param ErrorMessageList: Error message tuple list the language and its message
    727     # @param Lang: the language of setting
    728     # @return: the error message described in the related UNI file
    729     def GetEnErrorMessage(self, ErrorMessageList):
    730         if self.FullPath:
    731             pass
    732         Lang = TAB_LANGUAGE_EN_US
    733         for (Language, Message) in ErrorMessageList:
    734             if Language == Lang:
    735                 return Message
    736         for (Language, Message) in ErrorMessageList:
    737             if Language.find(TAB_LANGUAGE_EN) >= 0:
    738                 return Message
    739         else:
    740             try:
    741                 return ErrorMessageList[0][1]
    742             except IndexError:
    743                 return ''
    744         return ''    
    745         
    746     ##
    747     # Replace the strings for Python eval function.
    748     # @param ReplaceValue: The string that needs to be replaced. 
    749     # @return: The string was replaced, then eval function is always making out it.     
    750     def ReplaceForEval(self, ReplaceValue, IsRange=False, IsExpr=False):
    751         if self.FullPath:
    752             pass
    753         #
    754         # deal with "NOT EQ", "NOT LT", "NOT GT", "NOT LE", "NOT GE", "NOT NOT" 
    755         #
    756         NOTNOT_Pattern = '[\t\s]*NOT[\t\s]+NOT[\t\s]*'
    757         NOTGE_Pattern = '[\t\s]*NOT[\t\s]+GE[\t\s]*'
    758         NOTLE_Pattern = '[\t\s]*NOT[\t\s]+LE[\t\s]*'
    759         NOTGT_Pattern = '[\t\s]*NOT[\t\s]+GT[\t\s]*'
    760         NOTLT_Pattern = '[\t\s]*NOT[\t\s]+LT[\t\s]*'
    761         NOTEQ_Pattern = '[\t\s]*NOT[\t\s]+EQ[\t\s]*'
    762         ReplaceValue = re.compile(NOTNOT_Pattern).sub('', ReplaceValue)
    763         ReplaceValue = re.compile(NOTLT_Pattern).sub('x >= ', ReplaceValue)
    764         ReplaceValue = re.compile(NOTGT_Pattern).sub('x <= ', ReplaceValue)
    765         ReplaceValue = re.compile(NOTLE_Pattern).sub('x > ', ReplaceValue)
    766         ReplaceValue = re.compile(NOTGE_Pattern).sub('x < ', ReplaceValue)
    767         ReplaceValue = re.compile(NOTEQ_Pattern).sub('x != ', ReplaceValue)
    768         
    769         if IsRange:
    770             ReplaceValue = ReplaceValue.replace('EQ', 'x ==')
    771             ReplaceValue = ReplaceValue.replace('LT', 'x <')
    772             ReplaceValue = ReplaceValue.replace('LE', 'x <=')
    773             ReplaceValue = ReplaceValue.replace('GT', 'x >')
    774             ReplaceValue = ReplaceValue.replace('GE', 'x >=')
    775             ReplaceValue = ReplaceValue.replace('XOR', 'x ^')
    776         elif IsExpr:
    777             ReplaceValue = ReplaceValue.replace('EQ', '==')
    778             ReplaceValue = ReplaceValue.replace('NE', '!=')
    779             ReplaceValue = ReplaceValue.replace('LT', '<')
    780             ReplaceValue = ReplaceValue.replace('LE', '<=')
    781             ReplaceValue = ReplaceValue.replace('GT', '>')
    782             ReplaceValue = ReplaceValue.replace('GE', '>=')  
    783             ReplaceValue = ReplaceValue.replace('XOR', '^')  
    784             
    785         ReplaceValue = ReplaceValue.replace('AND', 'and')
    786         ReplaceValue = ReplaceValue.replace('&&', ' and ')
    787         ReplaceValue = ReplaceValue.replace('xor', '^')
    788         ReplaceValue = ReplaceValue.replace('OR', 'or')
    789         ReplaceValue = ReplaceValue.replace('||', ' or ')
    790         ReplaceValue = ReplaceValue.replace('NOT', 'not')
    791         if ReplaceValue.find('!') >= 0 and ReplaceValue[ReplaceValue.index('!') + 1] != '=':
    792             ReplaceValue = ReplaceValue.replace('!', ' not ')        
    793         if '.' in ReplaceValue:
    794             Pattern = '[a-zA-Z0-9]{1,}\.[a-zA-Z0-9]{1,}'
    795             MatchedList = re.findall(Pattern, ReplaceValue)
    796             for MatchedItem in MatchedList:
    797                 if MatchedItem not in self.PcdDefaultValueDict:
    798                     Logger.Error("Dec File Parser", FORMAT_INVALID, Message=ST.ERR_DECPARSE_PCD_NODEFINED % MatchedItem,
    799                                      File=self.FullPath)
    800                     
    801                 ReplaceValue = ReplaceValue.replace(MatchedItem, self.PcdDefaultValueDict[MatchedItem])
    802 
    803         return ReplaceValue
    804 
    805     ##
    806     # Check pcd's default value according to the pcd's description
    807     #
    808     def CheckPcdValue(self):
    809         for Pcd in self.GetPcdList():
    810             self.PcdDefaultValueDict[TAB_SPLIT.join((Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName())).strip()] = \
    811             Pcd.GetDefaultValue()
    812         
    813         for Pcd in self.GetPcdList():
    814             ValidationExpressions = []
    815             PcdGuidName = TAB_SPLIT.join((Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName()))
    816             Valids = Pcd.GetPcdErrorsList()
    817             for Valid in Valids:
    818                 Expression = Valid.GetExpression()
    819                 if Expression:
    820                     #
    821                     # Delete the 'L' prefix of a quoted string, this operation is for eval()
    822                     #
    823                     QUOTED_PATTERN = '[\t\s]*L?"[^"]*"'
    824                     QuotedMatchedObj = re.search(QUOTED_PATTERN, Expression)
    825                     if QuotedMatchedObj:
    826                         MatchedStr = QuotedMatchedObj.group().strip()
    827                         if MatchedStr.startswith('L'):
    828                             Expression = Expression.replace(MatchedStr, MatchedStr[1:].strip())  
    829 
    830                     Expression = self.ReplaceForEval(Expression, IsExpr=True)
    831                     Expression = Expression.replace(PcdGuidName, 'x')
    832                     Message = self.GetEnErrorMessage(Valid.GetErrorMessageList())
    833                     ValidationExpressions.append((Expression, Message))                   
    834                 
    835                 ValidList = Valid.GetValidValue()
    836                 if ValidList:
    837                     ValidValue = 'x in %s' % [eval(v) for v in ValidList.split(' ') if v]
    838                     Message = self.GetEnErrorMessage(Valid.GetErrorMessageList())
    839                     ValidationExpressions.append((ValidValue, Message))
    840                     
    841                 ValidValueRange = Valid.GetValidValueRange()                
    842                 if ValidValueRange:
    843                     ValidValueRange = self.ReplaceForEval(ValidValueRange, IsRange=True)
    844                     if ValidValueRange.find('-') >= 0:
    845                         ValidValueRange = ValidValueRange.replace('-', '<= x <=')
    846                     elif not ValidValueRange.startswith('x ') and not ValidValueRange.startswith('not ') \
    847                         and not ValidValueRange.startswith('not(') and not ValidValueRange.startswith('('):
    848                         ValidValueRange = 'x %s' % ValidValueRange
    849                     Message = self.GetEnErrorMessage(Valid.GetErrorMessageList())
    850                     ValidationExpressions.append((ValidValueRange, Message))
    851                     
    852             DefaultValue = self.PcdDefaultValueDict[PcdGuidName.strip()]
    853             #
    854             # Delete the 'L' prefix of a quoted string, this operation is for eval()
    855             #
    856             QUOTED_PATTERN = '[\t\s]*L?"[^"]*"'
    857             QuotedMatchedObj = re.search(QUOTED_PATTERN, DefaultValue)
    858             if QuotedMatchedObj:
    859                 MatchedStr = QuotedMatchedObj.group().strip()
    860                 if MatchedStr.startswith('L'):
    861                     DefaultValue = DefaultValue.replace(MatchedStr, MatchedStr[1:].strip())
    862                     
    863             try:
    864                 DefaultValue = eval(DefaultValue.replace('TRUE', 'True').replace('true', 'True')
    865                                         .replace('FALSE', 'False').replace('false', 'False'))
    866             except BaseException:
    867                 pass
    868 
    869             for (Expression, Msg) in ValidationExpressions:
    870                 try:
    871                     if not eval(Expression, {'x':DefaultValue}):
    872                         Logger.Error("Dec File Parser", FORMAT_INVALID, ExtraData='%s, value = %s' %\
    873                                      (PcdGuidName, DefaultValue), Message=Msg, File=self.FullPath)
    874                 except TypeError:
    875                     Logger.Error("Dec File Parser", FORMAT_INVALID, ExtraData=PcdGuidName, \
    876                                     Message=Msg, File=self.FullPath)
    877 
    878     ## GenModuleFileList
    879     #
    880     def GenModuleFileList(self, ContainerFile):        
    881         ModuleFileList = []
    882         ContainerFileName = os.path.basename(ContainerFile)
    883         ContainerFilePath = os.path.dirname(ContainerFile)
    884         for Item in GetFiles(ContainerFilePath, 
    885                         ['CVS', '.svn'] + self.GetIncludePathList(), False):
    886             ExtName = os.path.splitext(Item)[1]
    887             if ExtName.lower() == '.inf':
    888                 ModuleFileList.append(Item)
    889             elif ExtName.upper() == '.DEC' and self.CheckMulDec:
    890                 if Item == ContainerFileName:
    891                     continue
    892                 Logger.Error('MkPkg', 
    893                              UPT_MUL_DEC_ERROR,
    894                              ST.ERR_MUL_DEC_ERROR%(ContainerFilePath, 
    895                                                    ContainerFileName, 
    896                                                    Item))
    897                 
    898         self.SetModuleFileList(ModuleFileList)
    899     
    900     ## Show detailed information of Package
    901     #
    902     # Print all members and their values of Package class
    903     #
    904     def ShowPackage(self):
    905         print '\nName =', self.GetName()
    906         print '\nBaseName =', self.GetBaseName()
    907         print '\nVersion =', self.GetVersion() 
    908         print '\nGuid =', self.GetGuid()
    909         
    910         print '\nStandardIncludes = %d ' \
    911             % len(self.GetStandardIncludeFileList()),
    912         for Item in self.GetStandardIncludeFileList():
    913             print Item.GetFilePath(), '  ', Item.GetSupArchList()
    914         print '\nPackageIncludes = %d \n' \
    915             % len(self.GetPackageIncludeFileList()),
    916         for Item in self.GetPackageIncludeFileList():
    917             print Item.GetFilePath(), '  ', Item.GetSupArchList()
    918              
    919         print '\nGuids =', self.GetGuidList()
    920         for Item in self.GetGuidList():
    921             print Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()
    922         print '\nProtocols =', self.GetProtocolList()
    923         for Item in self.GetProtocolList():
    924             print Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()
    925         print '\nPpis =', self.GetPpiList()
    926         for Item in self.GetPpiList():
    927             print Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()
    928         print '\nLibraryClasses =', self.GetLibraryClassList()
    929         for Item in self.GetLibraryClassList():
    930             print Item.GetLibraryClass(), Item.GetRecommendedInstance(), \
    931             Item.GetSupArchList()
    932         print '\nPcds =', self.GetPcdList()
    933         for Item in self.GetPcdList():
    934             print 'CName=', Item.GetCName(), 'TokenSpaceGuidCName=', \
    935                 Item.GetTokenSpaceGuidCName(), \
    936                 'DefaultValue=', Item.GetDefaultValue(), \
    937                 'ValidUsage=', Item.GetValidUsage(), \
    938                 'SupArchList', Item.GetSupArchList(), \
    939                 'Token=', Item.GetToken(), 'DatumType=', Item.GetDatumType()
    940  
    941         for Item in self.GetMiscFileList():
    942             print Item.GetName()
    943             for FileObjectItem in Item.GetFileList():
    944                 print FileObjectItem.GetURI()
    945         print '****************\n'
    946 
    947 ## GenPcdDeclaration
    948 #
    949 # @param ContainerFile:   File name of the DEC file
    950 # @param PcdInfo:         Pcd information, of format (TokenGuidCName, 
    951 #                         TokenName, Value, DatumType, Token, Type, 
    952 #                         GenericComment, TailComment, Arch)
    953 # @param Language: The language of HelpText, Prompt 
    954 # 
    955 def GenPcdDeclaration(ContainerFile, PcdInfo, Language, MacroReplaceDict):
    956     HelpStr = ''
    957     PromptStr = ''
    958     TailHelpStr = ''
    959     TokenGuidCName, TokenName, Value, DatumType, Token, Type, \
    960         GenericComment, TailComment, Arch = PcdInfo
    961     Pcd = PcdObject()
    962     Pcd.SetCName(TokenName)
    963     Pcd.SetToken(Token)
    964     Pcd.SetTokenSpaceGuidCName(TokenGuidCName)
    965     Pcd.SetDatumType(DatumType)
    966     Pcd.SetDefaultValue(Value)
    967     Pcd.SetValidUsage(Type)
    968     #
    969     #  MaxDatumSize is required field for 'VOID*' PCD
    970     #
    971     if DatumType == TAB_PTR_TYPE_PCD:
    972         Pcd.SetMaxDatumSize(ITEM_UNDEFINED)
    973 
    974     SupArchList = [Arch]
    975     Pcd.SetSupArchList(SupArchList)
    976     
    977     if GenericComment:
    978         HelpStr, PcdErrList, PromptStr = ParseDecPcdGenericComment(GenericComment, 
    979                                                                    ContainerFile, 
    980                                                                    TokenGuidCName, 
    981                                                                    TokenName,
    982                                                                    MacroReplaceDict)
    983         if PcdErrList:
    984             Pcd.SetPcdErrorsList(PcdErrList)
    985 
    986     if TailComment:
    987         SupModuleList, TailHelpStr = ParseDecPcdTailComment(TailComment, 
    988                                                         ContainerFile)
    989         if SupModuleList:
    990             Pcd.SetSupModuleList(SupModuleList)
    991     
    992     if HelpStr and (not HelpStr.endswith('\n')) and TailHelpStr:
    993         HelpStr += '\n'
    994     HelpStr += TailHelpStr
    995     if HelpStr:
    996         HelpTxtObj = TextObject()
    997         HelpTxtObj.SetLang(Language)   
    998         HelpTxtObj.SetString(HelpStr)
    999         Pcd.SetHelpTextList([HelpTxtObj])
   1000     if PromptStr:
   1001         TxtObj = TextObject()
   1002         TxtObj.SetLang(Language)
   1003         TxtObj.SetString(PromptStr)
   1004         Pcd.SetPromptList([TxtObj])
   1005 
   1006     return Pcd
   1007