1## @file DecPomAlignment.py
2# This file contained the adapter for convert INF parser object to POM Object
3#
4# Copyright (c) 2011 - 2014, 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'''
16DecPomAlignment
17'''
18
19##
20# Import Modules
21#
22import os.path
23from os import sep
24import platform
25
26import re
27import Logger.Log as Logger
28from Logger import StringTable as ST
29from Logger.ToolError import UPT_MUL_DEC_ERROR
30from Logger.ToolError import FORMAT_INVALID
31
32from Library.Parsing import NormPath
33from Library.DataType import ARCH_LIST
34from Library.DataType import TAB_GUIDS
35from Library.DataType import TAB_PROTOCOLS
36from Library.DataType import TAB_PPIS
37from Library.DataType import TAB_DEC_DEFINES_PACKAGE_NAME
38from Library.DataType import TAB_DEC_DEFINES_PACKAGE_GUID
39from Library.DataType import TAB_DEC_DEFINES_PACKAGE_VERSION
40from Library.DataType import TAB_DEC_DEFINES_DEC_SPECIFICATION
41from Library.DataType import TAB_DEC_DEFINES_PKG_UNI_FILE
42from Library.DataType import TAB_ARCH_COMMON
43from Library.DataType import TAB_INCLUDES
44from Library.DataType import TAB_LIBRARY_CLASSES
45from Library.DataType import TAB_PCDS
46from Library.DataType import TAB_PCDS_FIXED_AT_BUILD_NULL
47from Library.DataType import TAB_PCDS_PATCHABLE_IN_MODULE_NULL
48from Library.DataType import TAB_PCDS_FEATURE_FLAG_NULL
49from Library.DataType import TAB_PCDS_DYNAMIC_EX_NULL
50from Library.DataType import TAB_PCDS_DYNAMIC_NULL
51from Library.DataType import TAB_PTR_TYPE_PCD
52from Library.DataType import ITEM_UNDEFINED
53from Library.DataType import TAB_DEC_BINARY_ABSTRACT
54from Library.DataType import TAB_DEC_BINARY_DESCRIPTION
55from Library.DataType import TAB_LANGUAGE_EN_US
56from Library.DataType import TAB_BINARY_HEADER_IDENTIFIER
57from Library.DataType import TAB_BINARY_HEADER_USERID
58from Library.DataType import TAB_LANGUAGE_EN_X
59from Library.DataType import TAB_LANGUAGE_EN
60from Library.DataType import TAB_STR_TOKENCNAME
61from Library.DataType import TAB_STR_TOKENPROMPT
62from Library.DataType import TAB_STR_TOKENHELP
63from Library.DataType import TAB_STR_TOKENERR
64from Library.DataType import TAB_HEX_START
65from Library.DataType import TAB_SPLIT
66from Library.CommentParsing import ParseHeaderCommentSection
67from Library.CommentParsing import ParseGenericComment
68from Library.CommentParsing import ParseDecPcdGenericComment
69from Library.CommentParsing import ParseDecPcdTailComment
70from Library.Misc import GetFiles
71from Library.Misc import Sdict
72from Library.Misc import GetRelativePath
73from Library.Misc import PathClass
74from Library.Misc import ValidateUNIFilePath
75from Library.UniClassObject import UniFileClassObject
76from Library.UniClassObject import ConvertSpecialUnicodes
77from Library.UniClassObject import GetLanguageCode1766
78from Library.ParserValidate import IsValidPath
79from Parser.DecParser import Dec
80from Object.POM.PackageObject import PackageObject
81from Object.POM.CommonObject import UserExtensionObject
82from Object.POM.CommonObject import IncludeObject
83from Object.POM.CommonObject import GuidObject
84from Object.POM.CommonObject import ProtocolObject
85from Object.POM.CommonObject import PpiObject
86from Object.POM.CommonObject import LibraryClassObject
87from Object.POM.CommonObject import PcdObject
88from Object.POM.CommonObject import TextObject
89from Object.POM.CommonObject import MiscFileObject
90from Object.POM.CommonObject import FileObject
91
92
93## DecPomAlignment
94#
95# Inherited from PackageObject
96#
97class DecPomAlignment(PackageObject):
98    def __init__(self, Filename, WorkspaceDir = None, CheckMulDec = False):
99        PackageObject.__init__(self)
100        self.UserExtensions = ''
101        self.WorkspaceDir = WorkspaceDir
102        self.SupArchList = ARCH_LIST
103        self.CheckMulDec = CheckMulDec
104        self.DecParser = None
105        self.UniFileClassObject = None
106        self.PcdDefaultValueDict = {}
107
108        #
109        # Load Dec file
110        #
111        self.LoadDecFile(Filename)
112
113        #
114        # Transfer to Package Object if IsToPackage is True
115        #
116        self.DecToPackage()
117
118    ## Load Dec file
119    #
120    # Load the file if it exists
121    #
122    # @param Filename:  Input value for filename of Dec file
123    #
124    def LoadDecFile(self, Filename):
125        #
126        # Insert a record for file
127        #
128        Filename = NormPath(Filename)
129        (Path, Name) = os.path.split(Filename)
130        self.SetFullPath(Filename)
131        self.SetRelaPath(Path)
132        self.SetFileName(Name)
133        self.SetPackagePath(GetRelativePath(Path, self.WorkspaceDir))
134        self.SetCombinePath(GetRelativePath(Filename, self.WorkspaceDir))
135
136        self.DecParser = Dec(Filename)
137
138    ## Transfer to Package Object
139    #
140    # Transfer all contents of a Dec file to a standard Package Object
141    #
142    def DecToPackage(self):
143        #
144        # Init global information for the file
145        #
146        ContainerFile = self.GetFullPath()
147
148        #
149        # Generate Package Header
150        #
151        self.GenPackageHeader(ContainerFile)
152
153        #
154        # Generate Includes
155        #
156        self.GenIncludes(ContainerFile)
157
158        #
159        # Generate Guids
160        #
161        self.GenGuidProtocolPpis(TAB_GUIDS, ContainerFile)
162
163        #
164        # Generate Protocols
165        #
166        self.GenGuidProtocolPpis(TAB_PROTOCOLS, ContainerFile)
167
168        #
169        # Generate Ppis
170        #
171        self.GenGuidProtocolPpis(TAB_PPIS, ContainerFile)
172
173        #
174        # Generate LibraryClasses
175        #
176        self.GenLibraryClasses(ContainerFile)
177
178        #
179        # Generate Pcds
180        #
181        self.GenPcds(ContainerFile)
182
183        #
184        # Generate Module File list, will be used later on to generate
185        # distribution
186        #
187        self.GenModuleFileList(ContainerFile)
188
189        #
190        # Generate user extensions
191        #
192        self.GenUserExtensions()
193
194    ## Generate user extension
195    #
196    #
197    def GenUserExtensions(self):
198        UEObj = self.DecParser.GetUserExtensionSectionObject()
199        UEList = UEObj.GetAllUserExtensions()
200        for Item in UEList:
201            if not Item.UserString:
202                continue
203            UserExtension = UserExtensionObject()
204            UserId = Item.UserId
205            if UserId.startswith('"') and UserId.endswith('"'):
206                UserId = UserId[1:-1]
207            UserExtension.SetUserID(UserId)
208            Identifier = Item.IdString
209            if Identifier.startswith('"') and Identifier.endswith('"'):
210                Identifier = Identifier[1:-1]
211            #
212            # Generate miscellaneous files of DEC file
213            #
214            if UserId == 'TianoCore' and Identifier == 'ExtraFiles':
215                self.GenMiscFiles(Item.UserString)
216            UserExtension.SetIdentifier(Identifier)
217            UserExtension.SetStatement(Item.UserString)
218            UserExtension.SetSupArchList(
219                Item.ArchAndModuleType
220            )
221            self.SetUserExtensionList(
222                self.GetUserExtensionList() + [UserExtension]
223            )
224
225    ## Generate miscellaneous files on DEC file
226    #
227    #
228    def GenMiscFiles(self, Content):
229        MiscFileObj = MiscFileObject()
230        for Line in Content.splitlines():
231            FileName = ''
232            if '#' in Line:
233                FileName = Line[:Line.find('#')]
234            else:
235                FileName = Line
236            if FileName:
237                if IsValidPath(FileName, self.GetRelaPath()):
238                    FileObj = FileObject()
239                    FileObj.SetURI(FileName)
240                    MiscFileObj.SetFileList(MiscFileObj.GetFileList()+[FileObj])
241                else:
242                    Logger.Error("InfParser",
243                                 FORMAT_INVALID,
244                                 ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(Line),
245                                 File=self.GetFileName(),
246                                 ExtraData=Line)
247        self.SetMiscFileList(self.GetMiscFileList()+[MiscFileObj])
248
249    ## Generate Package Header
250    #
251    # Gen Package Header of Dec as <Key> = <Value>
252    #
253    # @param ContainerFile: The Dec file full path
254    #
255    def GenPackageHeader(self, ContainerFile):
256        Logger.Debug(2, "Generate PackageHeader ...")
257        DefinesDict = {}
258
259        #
260        # Update all defines item in database
261        #
262        DefObj = self.DecParser.GetDefineSectionObject()
263        for Item in DefObj.GetDefines():
264            #
265            # put items into Dict except for PackageName, Guid, Version, DEC_SPECIFICATION
266            #
267            SkipItemList = [TAB_DEC_DEFINES_PACKAGE_NAME, \
268                TAB_DEC_DEFINES_PACKAGE_GUID, TAB_DEC_DEFINES_PACKAGE_VERSION, \
269                TAB_DEC_DEFINES_DEC_SPECIFICATION, TAB_DEC_DEFINES_PKG_UNI_FILE]
270            if Item.Key in SkipItemList:
271                continue
272            DefinesDict['%s = %s' % (Item.Key, Item.Value)] = TAB_ARCH_COMMON
273
274        self.SetBaseName(DefObj.GetPackageName())
275        self.SetVersion(DefObj.GetPackageVersion())
276#        self.SetName(DefObj.GetPackageName() + ' Version ' + \
277#                     DefObj.GetPackageVersion())
278        self.SetName(os.path.splitext(self.GetFileName())[0])
279        self.SetGuid(DefObj.GetPackageGuid())
280        if DefObj.GetPackageUniFile():
281            ValidateUNIFilePath(DefObj.GetPackageUniFile())
282            self.UniFileClassObject = \
283            UniFileClassObject([PathClass(os.path.join(DefObj.GetPackagePath(), DefObj.GetPackageUniFile()))])
284        else:
285            self.UniFileClassObject = None
286
287        if DefinesDict:
288            UserExtension = UserExtensionObject()
289            UserExtension.SetDefinesDict(DefinesDict)
290            UserExtension.SetIdentifier('DefineModifiers')
291            UserExtension.SetUserID('EDK2')
292            self.SetUserExtensionList(
293                self.GetUserExtensionList() + [UserExtension]
294            )
295
296        #
297        # Get File header information
298        #
299        if self.UniFileClassObject:
300            Lang = TAB_LANGUAGE_EN_X
301        else:
302            Lang = TAB_LANGUAGE_EN_US
303        Abstract, Description, Copyright, License = \
304            ParseHeaderCommentSection(self.DecParser.GetHeadComment(),
305                                      ContainerFile)
306        if Abstract:
307            self.SetAbstract((Lang, Abstract))
308        if Description:
309            self.SetDescription((Lang, Description))
310        if Copyright:
311            self.SetCopyright(('', Copyright))
312        if License:
313            self.SetLicense(('', License))
314
315        #
316        # Get Binary header information
317        #
318        if self.DecParser.BinaryHeadComment:
319            Abstract, Description, Copyright, License = \
320                ParseHeaderCommentSection(self.DecParser.BinaryHeadComment,
321                                      ContainerFile, True)
322
323            if not Abstract  or not Description or not Copyright or not License:
324                Logger.Error('MkPkg',
325                             FORMAT_INVALID,
326                             ST.ERR_INVALID_BINARYHEADER_FORMAT,
327                             ContainerFile)
328            else:
329                self.SetBinaryHeaderAbstract((Lang, Abstract))
330                self.SetBinaryHeaderDescription((Lang, Description))
331                self.SetBinaryHeaderCopyright(('', Copyright))
332                self.SetBinaryHeaderLicense(('', License))
333
334        BinaryAbstractList = []
335        BinaryDescriptionList = []
336
337        #Get Binary header from UNI file
338        # Initialize the UniStrDict dictionary, top keys are language codes
339        UniStrDict = {}
340        if self.UniFileClassObject:
341            UniStrDict = self.UniFileClassObject.OrderedStringList
342            for Lang in UniStrDict:
343                for StringDefClassObject in UniStrDict[Lang]:
344                    Lang = GetLanguageCode1766(Lang)
345                    if StringDefClassObject.StringName == TAB_DEC_BINARY_ABSTRACT:
346                        if (Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue)) \
347                        not in self.GetBinaryHeaderAbstract():
348                            BinaryAbstractList.append((Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue)))
349                    if StringDefClassObject.StringName == TAB_DEC_BINARY_DESCRIPTION:
350                        if (Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue)) \
351                        not in self.GetBinaryHeaderDescription():
352                            BinaryDescriptionList.append((Lang,
353                                                          ConvertSpecialUnicodes(StringDefClassObject.StringValue)))
354        #Combine Binary header from DEC file and UNI file
355        BinaryAbstractList = self.GetBinaryHeaderAbstract() + BinaryAbstractList
356        BinaryDescriptionList = self.GetBinaryHeaderDescription() + BinaryDescriptionList
357        BinaryCopyrightList = self.GetBinaryHeaderCopyright()
358        BinaryLicenseList = self.GetBinaryHeaderLicense()
359        #Generate the UserExtensionObject for TianoCore."BinaryHeader"
360        if BinaryAbstractList or BinaryDescriptionList or BinaryCopyrightList or BinaryLicenseList:
361            BinaryUserExtension = UserExtensionObject()
362            BinaryUserExtension.SetBinaryAbstract(BinaryAbstractList)
363            BinaryUserExtension.SetBinaryDescription(BinaryDescriptionList)
364            BinaryUserExtension.SetBinaryCopyright(BinaryCopyrightList)
365            BinaryUserExtension.SetBinaryLicense(BinaryLicenseList)
366            BinaryUserExtension.SetIdentifier(TAB_BINARY_HEADER_IDENTIFIER)
367            BinaryUserExtension.SetUserID(TAB_BINARY_HEADER_USERID)
368            self.SetUserExtensionList(self.GetUserExtensionList() + [BinaryUserExtension])
369
370
371    ## GenIncludes
372    #
373    # Gen Includes of Dec
374    #
375    # @param ContainerFile: The Dec file full path
376    #
377    def GenIncludes(self, ContainerFile):
378        if ContainerFile:
379            pass
380        Logger.Debug(2, "Generate %s ..." % TAB_INCLUDES)
381        IncludesDict = Sdict()
382
383        IncObj = self.DecParser.GetIncludeSectionObject()
384        for Item in IncObj.GetAllIncludes():
385            IncludePath = os.path.normpath(Item.File)
386            if platform.system() != 'Windows' and platform.system() != 'Microsoft':
387                IncludePath = IncludePath.replace('\\', '/')
388            if IncludePath in IncludesDict:
389                if Item.GetArchList() == [TAB_ARCH_COMMON] or IncludesDict[IncludePath] == [TAB_ARCH_COMMON]:
390                    IncludesDict[IncludePath] = [TAB_ARCH_COMMON]
391                else:
392                    IncludesDict[IncludePath] = IncludesDict[IncludePath] + Item.GetArchList()
393            else:
394                IncludesDict[IncludePath] = Item.GetArchList()
395
396        #
397        # get the  standardIncludeFileList(industry), packageIncludeFileList
398        # (others) for PackageObject
399        #
400        PackagePath = os.path.split(self.GetFullPath())[0]
401        IncludePathList = \
402            [os.path.normpath(Path) + sep for Path in IncludesDict.keys()]
403        IncludePathList.sort()
404
405        #
406        # get a non-overlap set of include path, IncludePathList should be
407        # sorted, and path should be end with path seperator '\'
408        #
409        NonOverLapList = []
410        for Path1 in IncludePathList:
411            for Path2 in NonOverLapList:
412                if Path1.startswith(Path2):
413                    break
414            else:
415                NonOverLapList.append(Path1)
416        #
417        # revert the list so the longest path shown first in list, also need
418        # to remove the extra path seperator '\'
419        # as this list is used to search the supported Arch info
420        #
421        for IndexN in range (0, len(IncludePathList)):
422            IncludePathList[IndexN] = os.path.normpath(IncludePathList[IndexN])
423        IncludePathList.sort()
424        IncludePathList.reverse()
425        #
426        # save the include path list for later usage
427        #
428        self.SetIncludePathList(IncludePathList)
429        StandardIncludeFileList = []
430        PackageIncludeFileList = []
431
432        IncludeFileList = []
433        for Path in NonOverLapList:
434            FileList = GetFiles(os.path.join(PackagePath, Path), ['CVS', '.svn'], False)
435            IncludeFileList += [os.path.normpath(os.path.join(Path, File)) for File in FileList]
436        for Includefile in IncludeFileList:
437            ExtName = os.path.splitext(Includefile)[1]
438            if ExtName.upper() == '.DEC' and self.CheckMulDec:
439                Logger.Error('MkPkg',
440                             UPT_MUL_DEC_ERROR,
441                             ST.ERR_MUL_DEC_ERROR%(os.path.dirname(ContainerFile),
442                                                   os.path.basename(ContainerFile),
443                                                   Includefile))
444
445            FileCombinePath = os.path.dirname(Includefile)
446            Include = IncludeObject()
447            for Path in IncludePathList:
448                if FileCombinePath.startswith(Path):
449                    SupArchList = IncludesDict[Path]
450                    break
451            Include.SetFilePath(Includefile)
452            Include.SetSupArchList(SupArchList)
453            if Includefile.find('IndustryStandard') != -1:
454                StandardIncludeFileList.append(Include)
455            else:
456                PackageIncludeFileList.append(Include)
457
458        self.SetStandardIncludeFileList(StandardIncludeFileList)
459
460        #
461        # put include path into the PackageIncludeFileList
462        #
463        PackagePathList = []
464        IncObj = self.DecParser.GetIncludeSectionObject()
465        for Item in IncObj.GetAllIncludes():
466            IncludePath = Item.File
467            Include = IncludeObject()
468            Include.SetFilePath(IncludePath)
469            Include.SetSupArchList(Item.GetArchList())
470            PackagePathList.append(Include)
471        self.SetPackageIncludeFileList(PackagePathList + PackageIncludeFileList)
472
473    ## GenPpis
474    #
475    # Gen Ppis of Dec
476    # <CName>=<GuidValue>
477    #
478    # @param ContainerFile: The Dec file full path
479    #
480    def GenGuidProtocolPpis(self, Type, ContainerFile):
481        if ContainerFile:
482            pass
483        Logger.Debug(2, "Generate %s ..." % Type)
484
485        Obj = None
486        Factory = None
487        if Type == TAB_GUIDS:
488            Obj = self.DecParser.GetGuidSectionObject()
489            def CreateGuidObject():
490                Object = GuidObject()
491                Object.SetGuidTypeList([])
492                Object.SetUsage(None)
493                Object.SetName(None)
494                return Object
495            Factory = CreateGuidObject
496        elif Type == TAB_PROTOCOLS:
497            Obj = self.DecParser.GetProtocolSectionObject()
498
499            def CreateProtocolObject():
500                return ProtocolObject()
501            Factory = CreateProtocolObject
502        elif Type == TAB_PPIS:
503            Obj = self.DecParser.GetPpiSectionObject()
504
505            def CreatePpiObject():
506                return PpiObject()
507            Factory = CreatePpiObject
508        else:
509            #
510            # Should not be here
511            #
512            return
513
514        DeclarationsList = []
515
516        #
517        # Go through each arch
518        #
519        for Item in Obj.GetGuidStyleAllItems():
520            Name = Item.GuidCName
521            Value = Item.GuidString
522            HelpTxt = ParseGenericComment(Item.GetHeadComment() + \
523                                          Item.GetTailComment())
524
525            ListObject = Factory()
526            ListObject.SetCName(Name)
527            ListObject.SetGuid(Value)
528            ListObject.SetSupArchList(Item.GetArchList())
529            if HelpTxt:
530                if self.UniFileClassObject:
531                    HelpTxt.SetLang(TAB_LANGUAGE_EN_X)
532                ListObject.SetHelpTextList([HelpTxt])
533
534            DeclarationsList.append(ListObject)
535
536        #
537        #GuidTypeList is abstracted from help
538        #
539        if Type == TAB_GUIDS:
540            self.SetGuidList(self.GetGuidList() + DeclarationsList)
541        elif Type == TAB_PROTOCOLS:
542            self.SetProtocolList(self.GetProtocolList() + DeclarationsList)
543        elif Type == TAB_PPIS:
544            self.SetPpiList(self.GetPpiList() + DeclarationsList)
545
546    ## GenLibraryClasses
547    #
548    # Gen LibraryClasses of Dec
549    # <CName>=<GuidValue>
550    #
551    # @param ContainerFile: The Dec file full path
552    #
553    def GenLibraryClasses(self, ContainerFile):
554        if ContainerFile:
555            pass
556        Logger.Debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES)
557        LibraryClassDeclarations = []
558
559        LibObj = self.DecParser.GetLibraryClassSectionObject()
560        for Item in LibObj.GetAllLibraryclasses():
561            LibraryClass = LibraryClassObject()
562            LibraryClass.SetLibraryClass(Item.Libraryclass)
563            LibraryClass.SetSupArchList(Item.GetArchList())
564            LibraryClass.SetIncludeHeader(Item.File)
565            HelpTxt = ParseGenericComment(Item.GetHeadComment() + \
566                                          Item.GetTailComment(), None, '@libraryclass')
567            if HelpTxt:
568                if self.UniFileClassObject:
569                    HelpTxt.SetLang(TAB_LANGUAGE_EN_X)
570                LibraryClass.SetHelpTextList([HelpTxt])
571            LibraryClassDeclarations.append(LibraryClass)
572
573        self.SetLibraryClassList(self.GetLibraryClassList() + \
574                                 LibraryClassDeclarations)
575
576    ## GenPcds
577    #
578    # Gen Pcds of Dec
579    # <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
580    #
581    # @param ContainerFile: The Dec file full path
582    #
583    def GenPcds(self, ContainerFile):
584        Logger.Debug(2, "Generate %s ..." % TAB_PCDS)
585        PcdObj = self.DecParser.GetPcdSectionObject()
586        #
587        # Get all Pcds
588        #
589        PcdDeclarations = []
590        IterList = [
591            (TAB_PCDS_FIXED_AT_BUILD_NULL,      'FixedPcd'),
592            (TAB_PCDS_PATCHABLE_IN_MODULE_NULL, 'PatchPcd'),
593            (TAB_PCDS_FEATURE_FLAG_NULL,        'FeaturePcd'),
594            (TAB_PCDS_DYNAMIC_EX_NULL,          'PcdEx'),
595            (TAB_PCDS_DYNAMIC_NULL,             'Pcd')]
596
597        PromptStrList = []
598        HelpStrList = []
599        PcdErrStrList = []
600        # Initialize UniStrDict dictionary, top keys are language codes
601        UniStrDict = {}
602        StrList = []
603
604        Language = ''
605        if self.UniFileClassObject:
606            Language = TAB_LANGUAGE_EN_X
607        else:
608            Language = TAB_LANGUAGE_EN_US
609
610        if self.UniFileClassObject:
611            UniStrDict = self.UniFileClassObject.OrderedStringList
612            for Lang in UniStrDict:
613                for StringDefClassObject in UniStrDict[Lang]:
614                    StrList = StringDefClassObject.StringName.split('_')
615                    # StringName format is STR_<TOKENSPACECNAME>_<PCDCNAME>_PROMPT
616                    if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[3] == TAB_STR_TOKENPROMPT:
617                        PromptStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \
618                                              StringDefClassObject.StringValue))
619                    # StringName format is STR_<TOKENSPACECNAME>_<PCDCNAME>_HELP
620                    if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[3] == TAB_STR_TOKENHELP:
621                        HelpStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \
622                                            StringDefClassObject.StringValue))
623                    # StringName format is STR_<TOKENSPACECNAME>_ERR_##
624                    if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[2] == TAB_STR_TOKENERR:
625                        PcdErrStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \
626                                              StringDefClassObject.StringValue))
627        #
628        # For each PCD type
629        #
630        for PcdType, Type in IterList:
631            #
632            # Go through all archs
633            #
634            # for Arch in self.SupArchList + [TAB_ARCH_COMMON]:
635            #
636            for Item in PcdObj.GetPcdsByType(PcdType.upper()):
637                PcdDeclaration = GenPcdDeclaration(
638                        ContainerFile,
639                        (Item.TokenSpaceGuidCName, Item.TokenCName,
640                        Item.DefaultValue, Item.DatumType, Item.TokenValue,
641                        Type, Item.GetHeadComment(), Item.GetTailComment(),''),
642                        Language,
643                        self.DecParser.GetDefineSectionMacro()
644                        )
645                PcdDeclaration.SetSupArchList(Item.GetArchListOfType(PcdType))
646
647                #
648                # Get PCD error message from PCD error comment section in DEC file
649                #
650                for PcdErr in PcdDeclaration.GetPcdErrorsList():
651                    if (PcdDeclaration.GetTokenSpaceGuidCName(), PcdErr.GetErrorNumber()) \
652                        in self.DecParser.PcdErrorCommentDict:
653                        Key = (PcdDeclaration.GetTokenSpaceGuidCName(), PcdErr.GetErrorNumber())
654                        PcdErr.SetErrorMessageList(PcdErr.GetErrorMessageList() + \
655                                                      [(Language, self.DecParser.PcdErrorCommentDict[Key])])
656
657                for Index in range(0, len(PromptStrList)):
658                    StrNameList = PromptStrList[Index][1].split('_')
659                    if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \
660                    StrNameList[2].lower() == Item.TokenCName.lower():
661                        TxtObj = TextObject()
662                        TxtObj.SetLang(PromptStrList[Index][0])
663                        TxtObj.SetString(PromptStrList[Index][2])
664                        for Prompt in PcdDeclaration.GetPromptList():
665                            if Prompt.GetLang() == TxtObj.GetLang() and \
666                                Prompt.GetString() == TxtObj.GetString():
667                                break
668                        else:
669                            PcdDeclaration.SetPromptList(PcdDeclaration.GetPromptList() + [TxtObj])
670
671                for Index in range(0, len(HelpStrList)):
672                    StrNameList = HelpStrList[Index][1].split('_')
673                    if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \
674                    StrNameList[2].lower() == Item.TokenCName.lower():
675                        TxtObj = TextObject()
676                        TxtObj.SetLang(HelpStrList[Index][0])
677                        TxtObj.SetString(HelpStrList[Index][2])
678                        for HelpStrObj in PcdDeclaration.GetHelpTextList():
679                            if HelpStrObj.GetLang() == TxtObj.GetLang() and \
680                                HelpStrObj.GetString() == TxtObj.GetString():
681                                break
682                        else:
683                            PcdDeclaration.SetHelpTextList(PcdDeclaration.GetHelpTextList() + [TxtObj])
684
685                #
686                # Get PCD error message from UNI file
687                #
688                for Index in range(0, len(PcdErrStrList)):
689                    StrNameList = PcdErrStrList[Index][1].split('_')
690                    if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \
691                        StrNameList[2].lower() == TAB_STR_TOKENERR.lower():
692                        for PcdErr in PcdDeclaration.GetPcdErrorsList():
693                            if PcdErr.GetErrorNumber().lower() == (TAB_HEX_START + StrNameList[3]).lower() and \
694                                (PcdErrStrList[Index][0], PcdErrStrList[Index][2]) not in PcdErr.GetErrorMessageList():
695                                PcdErr.SetErrorMessageList(PcdErr.GetErrorMessageList() + \
696                                                            [(PcdErrStrList[Index][0], PcdErrStrList[Index][2])])
697
698                #
699                # Check to prevent missing error message if a Pcd has the error code.
700                #
701                for PcdErr in PcdDeclaration.GetPcdErrorsList():
702                    if PcdErr.GetErrorNumber().strip():
703                        if not PcdErr.GetErrorMessageList():
704                            Logger.Error('UPT',
705                                         FORMAT_INVALID,
706                                         ST.ERR_DECPARSE_PCD_UNMATCHED_ERRORCODE % PcdErr.GetErrorNumber(),
707                                         ContainerFile,
708                                         PcdErr.GetLineNum(),
709                                         PcdErr.GetFileLine())
710
711                PcdDeclarations.append(PcdDeclaration)
712        self.SetPcdList(self.GetPcdList() + PcdDeclarations)
713        self.CheckPcdValue()
714
715    ##
716    # Get error message via language
717    # @param ErrorMessageList: Error message tuple list the language and its message
718    # @param Lang: the language of setting
719    # @return: the error message described in the related UNI file
720    def GetEnErrorMessage(self, ErrorMessageList):
721        if self.FullPath:
722            pass
723        Lang = TAB_LANGUAGE_EN_US
724        for (Language, Message) in ErrorMessageList:
725            if Language == Lang:
726                return Message
727        for (Language, Message) in ErrorMessageList:
728            if Language.find(TAB_LANGUAGE_EN) >= 0:
729                return Message
730        else:
731            try:
732                return ErrorMessageList[0][1]
733            except IndexError:
734                return ''
735        return ''
736
737    ##
738    # Replace the strings for Python eval function.
739    # @param ReplaceValue: The string that needs to be replaced.
740    # @return: The string was replaced, then eval function is always making out it.
741    def ReplaceForEval(self, ReplaceValue, IsRange=False, IsExpr=False):
742        if self.FullPath:
743            pass
744        #
745        # deal with "NOT EQ", "NOT LT", "NOT GT", "NOT LE", "NOT GE", "NOT NOT"
746        #
747        NOTNOT_Pattern = '[\t\s]*NOT[\t\s]+NOT[\t\s]*'
748        NOTGE_Pattern = '[\t\s]*NOT[\t\s]+GE[\t\s]*'
749        NOTLE_Pattern = '[\t\s]*NOT[\t\s]+LE[\t\s]*'
750        NOTGT_Pattern = '[\t\s]*NOT[\t\s]+GT[\t\s]*'
751        NOTLT_Pattern = '[\t\s]*NOT[\t\s]+LT[\t\s]*'
752        NOTEQ_Pattern = '[\t\s]*NOT[\t\s]+EQ[\t\s]*'
753        ReplaceValue = re.compile(NOTNOT_Pattern).sub('', ReplaceValue)
754        ReplaceValue = re.compile(NOTLT_Pattern).sub('x >= ', ReplaceValue)
755        ReplaceValue = re.compile(NOTGT_Pattern).sub('x <= ', ReplaceValue)
756        ReplaceValue = re.compile(NOTLE_Pattern).sub('x > ', ReplaceValue)
757        ReplaceValue = re.compile(NOTGE_Pattern).sub('x < ', ReplaceValue)
758        ReplaceValue = re.compile(NOTEQ_Pattern).sub('x != ', ReplaceValue)
759
760        if IsRange:
761            ReplaceValue = ReplaceValue.replace('EQ', 'x ==')
762            ReplaceValue = ReplaceValue.replace('LT', 'x <')
763            ReplaceValue = ReplaceValue.replace('LE', 'x <=')
764            ReplaceValue = ReplaceValue.replace('GT', 'x >')
765            ReplaceValue = ReplaceValue.replace('GE', 'x >=')
766            ReplaceValue = ReplaceValue.replace('XOR', 'x ^')
767        elif IsExpr:
768            ReplaceValue = ReplaceValue.replace('EQ', '==')
769            ReplaceValue = ReplaceValue.replace('NE', '!=')
770            ReplaceValue = ReplaceValue.replace('LT', '<')
771            ReplaceValue = ReplaceValue.replace('LE', '<=')
772            ReplaceValue = ReplaceValue.replace('GT', '>')
773            ReplaceValue = ReplaceValue.replace('GE', '>=')
774            ReplaceValue = ReplaceValue.replace('XOR', '^')
775
776        ReplaceValue = ReplaceValue.replace('AND', 'and')
777        ReplaceValue = ReplaceValue.replace('&&', ' and ')
778        ReplaceValue = ReplaceValue.replace('xor', '^')
779        ReplaceValue = ReplaceValue.replace('OR', 'or')
780        ReplaceValue = ReplaceValue.replace('||', ' or ')
781        ReplaceValue = ReplaceValue.replace('NOT', 'not')
782        if ReplaceValue.find('!') >= 0 and ReplaceValue[ReplaceValue.index('!') + 1] != '=':
783            ReplaceValue = ReplaceValue.replace('!', ' not ')
784        if '.' in ReplaceValue:
785            Pattern = '[a-zA-Z0-9]{1,}\.[a-zA-Z0-9]{1,}'
786            MatchedList = re.findall(Pattern, ReplaceValue)
787            for MatchedItem in MatchedList:
788                if MatchedItem not in self.PcdDefaultValueDict:
789                    Logger.Error("Dec File Parser", FORMAT_INVALID, Message=ST.ERR_DECPARSE_PCD_NODEFINED % MatchedItem,
790                                     File=self.FullPath)
791
792                ReplaceValue = ReplaceValue.replace(MatchedItem, self.PcdDefaultValueDict[MatchedItem])
793
794        return ReplaceValue
795
796    ##
797    # Check pcd's default value according to the pcd's description
798    #
799    def CheckPcdValue(self):
800        for Pcd in self.GetPcdList():
801            self.PcdDefaultValueDict[TAB_SPLIT.join((Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName())).strip()] = \
802            Pcd.GetDefaultValue()
803
804        for Pcd in self.GetPcdList():
805            ValidationExpressions = []
806            PcdGuidName = TAB_SPLIT.join((Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName()))
807            Valids = Pcd.GetPcdErrorsList()
808            for Valid in Valids:
809                Expression = Valid.GetExpression()
810                if Expression:
811                    #
812                    # Delete the 'L' prefix of a quoted string, this operation is for eval()
813                    #
814                    QUOTED_PATTERN = '[\t\s]*L?"[^"]*"'
815                    QuotedMatchedObj = re.search(QUOTED_PATTERN, Expression)
816                    if QuotedMatchedObj:
817                        MatchedStr = QuotedMatchedObj.group().strip()
818                        if MatchedStr.startswith('L'):
819                            Expression = Expression.replace(MatchedStr, MatchedStr[1:].strip())
820
821                    Expression = self.ReplaceForEval(Expression, IsExpr=True)
822                    Expression = Expression.replace(PcdGuidName, 'x')
823                    Message = self.GetEnErrorMessage(Valid.GetErrorMessageList())
824                    ValidationExpressions.append((Expression, Message))
825
826                ValidList = Valid.GetValidValue()
827                if ValidList:
828                    ValidValue = 'x in %s' % [eval(v) for v in ValidList.split(' ') if v]
829                    Message = self.GetEnErrorMessage(Valid.GetErrorMessageList())
830                    ValidationExpressions.append((ValidValue, Message))
831
832                ValidValueRange = Valid.GetValidValueRange()
833                if ValidValueRange:
834                    ValidValueRange = self.ReplaceForEval(ValidValueRange, IsRange=True)
835                    if ValidValueRange.find('-') >= 0:
836                        ValidValueRange = ValidValueRange.replace('-', '<= x <=')
837                    elif not ValidValueRange.startswith('x ') and not ValidValueRange.startswith('not ') \
838                        and not ValidValueRange.startswith('not(') and not ValidValueRange.startswith('('):
839                        ValidValueRange = 'x %s' % ValidValueRange
840                    Message = self.GetEnErrorMessage(Valid.GetErrorMessageList())
841                    ValidationExpressions.append((ValidValueRange, Message))
842
843            DefaultValue = self.PcdDefaultValueDict[PcdGuidName.strip()]
844            #
845            # Delete the 'L' prefix of a quoted string, this operation is for eval()
846            #
847            QUOTED_PATTERN = '[\t\s]*L?"[^"]*"'
848            QuotedMatchedObj = re.search(QUOTED_PATTERN, DefaultValue)
849            if QuotedMatchedObj:
850                MatchedStr = QuotedMatchedObj.group().strip()
851                if MatchedStr.startswith('L'):
852                    DefaultValue = DefaultValue.replace(MatchedStr, MatchedStr[1:].strip())
853
854            try:
855                DefaultValue = eval(DefaultValue.replace('TRUE', 'True').replace('true', 'True')
856                                        .replace('FALSE', 'False').replace('false', 'False'))
857            except BaseException:
858                pass
859
860            for (Expression, Msg) in ValidationExpressions:
861                try:
862                    if not eval(Expression, {'x':DefaultValue}):
863                        Logger.Error("Dec File Parser", FORMAT_INVALID, ExtraData='%s, value = %s' %\
864                                     (PcdGuidName, DefaultValue), Message=Msg, File=self.FullPath)
865                except TypeError:
866                    Logger.Error("Dec File Parser", FORMAT_INVALID, ExtraData=PcdGuidName, \
867                                    Message=Msg, File=self.FullPath)
868
869    ## GenModuleFileList
870    #
871    def GenModuleFileList(self, ContainerFile):
872        ModuleFileList = []
873        ContainerFileName = os.path.basename(ContainerFile)
874        ContainerFilePath = os.path.dirname(ContainerFile)
875        for Item in GetFiles(ContainerFilePath,
876                        ['CVS', '.svn'] + self.GetIncludePathList(), False):
877            ExtName = os.path.splitext(Item)[1]
878            if ExtName.lower() == '.inf':
879                ModuleFileList.append(Item)
880            elif ExtName.upper() == '.DEC' and self.CheckMulDec:
881                if Item == ContainerFileName:
882                    continue
883                Logger.Error('MkPkg',
884                             UPT_MUL_DEC_ERROR,
885                             ST.ERR_MUL_DEC_ERROR%(ContainerFilePath,
886                                                   ContainerFileName,
887                                                   Item))
888
889        self.SetModuleFileList(ModuleFileList)
890
891    ## Show detailed information of Package
892    #
893    # Print all members and their values of Package class
894    #
895    def ShowPackage(self):
896        print '\nName =', self.GetName()
897        print '\nBaseName =', self.GetBaseName()
898        print '\nVersion =', self.GetVersion()
899        print '\nGuid =', self.GetGuid()
900
901        print '\nStandardIncludes = %d ' \
902            % len(self.GetStandardIncludeFileList()),
903        for Item in self.GetStandardIncludeFileList():
904            print Item.GetFilePath(), '  ', Item.GetSupArchList()
905        print '\nPackageIncludes = %d \n' \
906            % len(self.GetPackageIncludeFileList()),
907        for Item in self.GetPackageIncludeFileList():
908            print Item.GetFilePath(), '  ', Item.GetSupArchList()
909
910        print '\nGuids =', self.GetGuidList()
911        for Item in self.GetGuidList():
912            print Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()
913        print '\nProtocols =', self.GetProtocolList()
914        for Item in self.GetProtocolList():
915            print Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()
916        print '\nPpis =', self.GetPpiList()
917        for Item in self.GetPpiList():
918            print Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()
919        print '\nLibraryClasses =', self.GetLibraryClassList()
920        for Item in self.GetLibraryClassList():
921            print Item.GetLibraryClass(), Item.GetRecommendedInstance(), \
922            Item.GetSupArchList()
923        print '\nPcds =', self.GetPcdList()
924        for Item in self.GetPcdList():
925            print 'CName=', Item.GetCName(), 'TokenSpaceGuidCName=', \
926                Item.GetTokenSpaceGuidCName(), \
927                'DefaultValue=', Item.GetDefaultValue(), \
928                'ValidUsage=', Item.GetValidUsage(), \
929                'SupArchList', Item.GetSupArchList(), \
930                'Token=', Item.GetToken(), 'DatumType=', Item.GetDatumType()
931
932        for Item in self.GetMiscFileList():
933            print Item.GetName()
934            for FileObjectItem in Item.GetFileList():
935                print FileObjectItem.GetURI()
936        print '****************\n'
937
938## GenPcdDeclaration
939#
940# @param ContainerFile:   File name of the DEC file
941# @param PcdInfo:         Pcd information, of format (TokenGuidCName,
942#                         TokenName, Value, DatumType, Token, Type,
943#                         GenericComment, TailComment, Arch)
944# @param Language: The language of HelpText, Prompt
945#
946def GenPcdDeclaration(ContainerFile, PcdInfo, Language, MacroReplaceDict):
947    HelpStr = ''
948    PromptStr = ''
949    TailHelpStr = ''
950    TokenGuidCName, TokenName, Value, DatumType, Token, Type, \
951        GenericComment, TailComment, Arch = PcdInfo
952    Pcd = PcdObject()
953    Pcd.SetCName(TokenName)
954    Pcd.SetToken(Token)
955    Pcd.SetTokenSpaceGuidCName(TokenGuidCName)
956    Pcd.SetDatumType(DatumType)
957    Pcd.SetDefaultValue(Value)
958    Pcd.SetValidUsage(Type)
959    #
960    #  MaxDatumSize is required field for 'VOID*' PCD
961    #
962    if DatumType == TAB_PTR_TYPE_PCD:
963        Pcd.SetMaxDatumSize(ITEM_UNDEFINED)
964
965    SupArchList = [Arch]
966    Pcd.SetSupArchList(SupArchList)
967
968    if GenericComment:
969        HelpStr, PcdErrList, PromptStr = ParseDecPcdGenericComment(GenericComment,
970                                                                   ContainerFile,
971                                                                   TokenGuidCName,
972                                                                   TokenName,
973                                                                   MacroReplaceDict)
974        if PcdErrList:
975            Pcd.SetPcdErrorsList(PcdErrList)
976
977    if TailComment:
978        SupModuleList, TailHelpStr = ParseDecPcdTailComment(TailComment,
979                                                        ContainerFile)
980        if SupModuleList:
981            Pcd.SetSupModuleList(SupModuleList)
982
983    if HelpStr and (not HelpStr.endswith('\n')) and TailHelpStr:
984        HelpStr += '\n'
985    HelpStr += TailHelpStr
986    if HelpStr:
987        HelpTxtObj = TextObject()
988        HelpTxtObj.SetLang(Language)
989        HelpTxtObj.SetString(HelpStr)
990        Pcd.SetHelpTextList([HelpTxtObj])
991    if PromptStr:
992        TxtObj = TextObject()
993        TxtObj.SetLang(Language)
994        TxtObj.SetString(PromptStr)
995        Pcd.SetPromptList([TxtObj])
996
997    return Pcd
998