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