1## @file GenDecFile.py
2#
3# This file contained the logical of transfer package object to DEC files.
4#
5# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
6#
7# This program and the accompanying materials are licensed and made available
8# under the terms and conditions of the BSD License which accompanies this
9# distribution. The full text of the license may be found at
10# http://opensource.org/licenses/bsd-license.php
11#
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14#
15
16'''
17GenDEC
18'''
19import os
20import stat
21import codecs
22import md5
23from Core.FileHook import __FileHookOpen__
24from Library.Parsing import GenSection
25from Library.CommentGenerating import GenHeaderCommentSection
26from Library.CommentGenerating import GenGenericCommentF
27from Library.CommentGenerating import GenDecTailComment
28from Library.CommentGenerating import _GetHelpStr
29from Library.Misc import GuidStringToGuidStructureString
30from Library.Misc import SaveFileOnChange
31from Library.Misc import ConvertPath
32from Library.Misc import GetLocalValue
33from Library.DataType import TAB_SPACE_SPLIT
34from Library.DataType import TAB_COMMA_SPLIT
35from Library.DataType import END_OF_LINE
36from Library.DataType import TAB_ARCH_COMMON
37from Library.DataType import TAB_VALUE_SPLIT
38from Library.DataType import TAB_COMMENT_SPLIT
39from Library.DataType import TAB_PCD_VALIDRANGE
40from Library.DataType import TAB_PCD_VALIDLIST
41from Library.DataType import TAB_PCD_EXPRESSION
42from Library.DataType import TAB_DEC_DEFINES_DEC_SPECIFICATION
43from Library.DataType import TAB_DEC_DEFINES_PACKAGE_NAME
44from Library.DataType import TAB_DEC_DEFINES_PACKAGE_GUID
45from Library.DataType import TAB_DEC_DEFINES_PACKAGE_VERSION
46from Library.DataType import TAB_DEC_DEFINES_PKG_UNI_FILE
47from Library.DataType import TAB_DEC_PACKAGE_ABSTRACT
48from Library.DataType import TAB_DEC_PACKAGE_DESCRIPTION
49from Library.DataType import TAB_DEC_BINARY_ABSTRACT
50from Library.DataType import TAB_DEC_BINARY_DESCRIPTION
51from Library.DataType import TAB_LANGUAGE_EN_X
52from Library.DataType import TAB_BINARY_HEADER_USERID
53from Library.DataType import TAB_BINARY_HEADER_IDENTIFIER
54from Library.DataType import TAB_COMMENT_EDK1_SPLIT
55from Library.DataType import TAB_ENCODING_UTF16LE
56from Library.DataType import TAB_CAPHEX_START
57from Library.DataType import TAB_HEX_START
58from Library.DataType import TAB_UNDERLINE_SPLIT
59from Library.DataType import TAB_STR_TOKENERR
60from Library.DataType import TAB_STR_TOKENCNAME
61from Library.DataType import TAB_PCD_ERROR_SECTION_COMMENT
62from Library.DataType import TAB_PCD_ERROR
63from Library.DataType import TAB_SECTION_START
64from Library.DataType import TAB_SECTION_END
65from Library.DataType import TAB_SPLIT
66from Library.UniClassObject import FormatUniEntry
67
68def GenPcd(Package, Content):
69    #
70    # generate [Pcd] section
71    # <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
72    #
73    ValidUsageDict = {}
74    for Pcd in Package.GetPcdList():
75        #
76        # Generate generic comment
77        #
78        HelpTextList = Pcd.GetHelpTextList()
79        HelpStr = _GetHelpStr(HelpTextList)
80        CommentStr = GenGenericCommentF(HelpStr, 2)
81
82        PromptList = Pcd.GetPromptList()
83        PromptStr = _GetHelpStr(PromptList)
84        CommentStr += GenGenericCommentF(PromptStr.strip(), 1, True)
85
86        PcdErrList = Pcd.GetPcdErrorsList()
87        for PcdErr in PcdErrList:
88            CommentStr += GenPcdErrComment(PcdErr)
89        Statement = CommentStr
90
91        CName = Pcd.GetCName()
92        TokenSpaceGuidCName = Pcd.GetTokenSpaceGuidCName()
93        DefaultValue = Pcd.GetDefaultValue()
94        DatumType = Pcd.GetDatumType()
95        Token = Pcd.GetToken()
96        ValidUsage = Pcd.GetValidUsage()
97
98        if ValidUsage == 'FeaturePcd':
99            ValidUsage = 'PcdsFeatureFlag'
100        elif ValidUsage == 'PatchPcd':
101            ValidUsage = 'PcdsPatchableInModule'
102        elif ValidUsage == 'FixedPcd':
103            ValidUsage = 'PcdsFixedAtBuild'
104        elif ValidUsage == 'Pcd':
105            ValidUsage = 'PcdsDynamic'
106        elif ValidUsage == 'PcdEx':
107            ValidUsage = 'PcdsDynamicEx'
108
109        if ValidUsage in ValidUsageDict:
110            NewSectionDict = ValidUsageDict[ValidUsage]
111        else:
112            NewSectionDict = {}
113            ValidUsageDict[ValidUsage] = NewSectionDict
114        Statement += TokenSpaceGuidCName + '.' + CName
115        Statement += '|' + DefaultValue
116        Statement += '|' + DatumType
117        Statement += '|' + Token
118        #
119        # generate tail comment
120        #
121        if Pcd.GetSupModuleList():
122            Statement += GenDecTailComment(Pcd.GetSupModuleList())
123
124        ArchList = Pcd.GetSupArchList()
125        ArchList.sort()
126        SortedArch = ' '.join(ArchList)
127        if SortedArch in NewSectionDict:
128            NewSectionDict[SortedArch] = \
129            NewSectionDict[SortedArch] + [Statement]
130        else:
131            NewSectionDict[SortedArch] = [Statement]
132
133    for ValidUsage in ValidUsageDict:
134        Content += GenSection(ValidUsage, ValidUsageDict[ValidUsage], True, True)
135
136    return Content
137
138def GenPcdErrorMsgSection(Package, Content):
139    if not Package.PcdErrorCommentDict:
140        return Content
141
142    #
143    # Generate '# [Error.<TokenSpcCName>]' section
144    #
145    Content += END_OF_LINE + END_OF_LINE
146    SectionComment = TAB_COMMENT_SPLIT + END_OF_LINE
147    SectionComment += TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_ERROR_SECTION_COMMENT + END_OF_LINE
148    SectionComment += TAB_COMMENT_SPLIT + END_OF_LINE
149    TokenSpcCNameList = []
150
151    #
152    # Get TokenSpcCName list in PcdErrorCommentDict in Package object
153    #
154    for (TokenSpcCName, ErrorNumber) in Package.PcdErrorCommentDict:
155        if TokenSpcCName not in TokenSpcCNameList:
156            TokenSpcCNameList.append(TokenSpcCName)
157
158    for TokenSpcCNameItem in TokenSpcCNameList:
159        SectionName = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_SECTION_START + TAB_PCD_ERROR + \
160                      TAB_SPLIT + TokenSpcCNameItem + TAB_SECTION_END + END_OF_LINE
161        Content += SectionComment
162        Content += SectionName
163        for (TokenSpcCName, ErrorNumber) in Package.PcdErrorCommentDict:
164            if TokenSpcCNameItem == TokenSpcCName:
165                PcdErrorMsg = GetLocalValue(Package.PcdErrorCommentDict[(TokenSpcCName, ErrorNumber)])
166                SectionItem = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_SPACE_SPLIT + \
167                              ErrorNumber + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT + \
168                              PcdErrorMsg + END_OF_LINE
169                Content += SectionItem
170
171    Content += TAB_COMMENT_SPLIT
172    return Content
173
174def GenGuidProtocolPpi(Package, Content):
175    #
176    # generate [Guids] section
177    #
178    NewSectionDict = {}
179
180    LeftOffset = 46
181    # Get the line offset need
182    # If the real one < the min one, use the min one
183    # else use the real one
184    for Guid in Package.GetGuidList():
185        if len(Guid.GetCName()) > LeftOffset:
186            LeftOffset = len(Guid.GetCName())
187
188    # Generate
189    for Guid in Package.GetGuidList():
190        #
191        # Generate generic comment
192        #
193        HelpTextList = Guid.GetHelpTextList()
194        HelpStr = _GetHelpStr(HelpTextList)
195        CommentStr = GenGenericCommentF(HelpStr, 2)
196
197        Statement = CommentStr
198        CName = Guid.GetCName()
199        Value = GuidStringToGuidStructureString(Guid.GetGuid())
200        Statement += CName.ljust(LeftOffset) + ' = ' + Value
201        #
202        # generate tail comment
203        #
204        if Guid.GetSupModuleList():
205            Statement += GenDecTailComment(Guid.GetSupModuleList())
206        ArchList = Guid.GetSupArchList()
207        ArchList.sort()
208        SortedArch = ' '.join(ArchList)
209        if SortedArch in NewSectionDict:
210            NewSectionDict[SortedArch] = \
211            NewSectionDict[SortedArch] + [Statement]
212        else:
213            NewSectionDict[SortedArch] = [Statement]
214
215    Content += GenSection('Guids', NewSectionDict, True, True)
216
217    #
218    # generate [Protocols] section
219    #
220    NewSectionDict = {}
221    LeftOffset = 46
222    # Get the line offset need
223    # If the real one < the min one, use the min one
224    # else use the real one
225    for Protocol in Package.GetProtocolList():
226        if len(Protocol.GetCName()) > LeftOffset:
227            LeftOffset = len(Protocol.GetCName())
228
229    for Protocol in Package.GetProtocolList():
230        #
231        # Generate generic comment
232        #
233        HelpTextList = Protocol.GetHelpTextList()
234        HelpStr = _GetHelpStr(HelpTextList)
235        CommentStr = GenGenericCommentF(HelpStr, 2)
236
237        Statement = CommentStr
238        CName = Protocol.GetCName()
239        Value = GuidStringToGuidStructureString(Protocol.GetGuid())
240        Statement += CName.ljust(LeftOffset) + ' = ' + Value
241
242        #
243        # generate tail comment
244        #
245        if Protocol.GetSupModuleList():
246            Statement += GenDecTailComment(Protocol.GetSupModuleList())
247        ArchList = Protocol.GetSupArchList()
248        ArchList.sort()
249        SortedArch = ' '.join(ArchList)
250        if SortedArch in NewSectionDict:
251            NewSectionDict[SortedArch] = \
252            NewSectionDict[SortedArch] + [Statement]
253        else:
254            NewSectionDict[SortedArch] = [Statement]
255
256    Content += GenSection('Protocols', NewSectionDict, True, True)
257
258    #
259    # generate [Ppis] section
260    #
261    NewSectionDict = {}
262    LeftOffset = 46
263    # Get the line offset need
264    # If the real one < the min one, use the min one
265    # else use the real one
266    for Ppi in Package.GetPpiList():
267        if len(Ppi.GetCName()) > LeftOffset:
268            LeftOffset = len(Ppi.GetCName())
269
270    for Ppi in Package.GetPpiList():
271        #
272        # Generate generic comment
273        #
274        HelpTextList = Ppi.GetHelpTextList()
275        HelpStr = _GetHelpStr(HelpTextList)
276        CommentStr = GenGenericCommentF(HelpStr, 2)
277
278        Statement = CommentStr
279        CName = Ppi.GetCName()
280        Value = GuidStringToGuidStructureString(Ppi.GetGuid())
281        Statement += CName.ljust(LeftOffset) + ' = ' + Value
282
283        #
284        # generate tail comment
285        #
286        if Ppi.GetSupModuleList():
287            Statement += GenDecTailComment(Ppi.GetSupModuleList())
288        ArchList = Ppi.GetSupArchList()
289        ArchList.sort()
290        SortedArch = ' '.join(ArchList)
291        if SortedArch in NewSectionDict:
292            NewSectionDict[SortedArch] = \
293            NewSectionDict[SortedArch] + [Statement]
294        else:
295            NewSectionDict[SortedArch] = [Statement]
296
297    Content += GenSection('Ppis', NewSectionDict, True, True)
298
299    return Content
300
301## Transfer Package Object to Dec files
302#
303# Transfer all contents of a standard Package Object to a Dec file
304#
305# @param Package:  A Package
306#
307def PackageToDec(Package, DistHeader = None):
308    #
309    # Init global information for the file
310    #
311    ContainerFile = Package.GetFullPath()
312
313    Content = ''
314
315    #
316    # Generate file header
317    #
318    PackageAbstract = GetLocalValue(Package.GetAbstract())
319    PackageDescription = GetLocalValue(Package.GetDescription())
320    PackageCopyright = ''
321    PackageLicense = ''
322    for (Lang, Copyright) in Package.GetCopyright():
323        if Lang:
324            pass
325        PackageCopyright = Copyright
326    for (Lang, License) in Package.GetLicense():
327        if Lang:
328            pass
329        PackageLicense = License
330    if not PackageAbstract and DistHeader:
331        PackageAbstract = GetLocalValue(DistHeader.GetAbstract())
332    if not PackageDescription and DistHeader:
333        PackageDescription = GetLocalValue(DistHeader.GetDescription())
334    if not PackageCopyright and DistHeader:
335        for (Lang, Copyright) in DistHeader.GetCopyright():
336            PackageCopyright = Copyright
337    if not PackageLicense and DistHeader:
338        for (Lang, License) in DistHeader.GetLicense():
339            PackageLicense = License
340
341    #
342    # Generate header comment section of DEC file
343    #
344    Content += GenHeaderCommentSection(PackageAbstract, \
345                                       PackageDescription, \
346                                       PackageCopyright, \
347                                       PackageLicense).replace('\r\n', '\n')
348
349    #
350    # Generate Binary header
351    #
352    for UserExtension in Package.GetUserExtensionList():
353        if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID \
354        and UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
355            PackageBinaryAbstract = GetLocalValue(UserExtension.GetBinaryAbstract())
356            PackageBinaryDescription = GetLocalValue(UserExtension.GetBinaryDescription())
357            PackageBinaryCopyright = ''
358            PackageBinaryLicense = ''
359            for (Lang, Copyright) in UserExtension.GetBinaryCopyright():
360                PackageBinaryCopyright = Copyright
361            for (Lang, License) in UserExtension.GetBinaryLicense():
362                PackageBinaryLicense = License
363            if PackageBinaryAbstract and PackageBinaryDescription and \
364            PackageBinaryCopyright and PackageBinaryLicense:
365                Content += GenHeaderCommentSection(PackageBinaryAbstract,
366                                           PackageBinaryDescription,
367                                           PackageBinaryCopyright,
368                                           PackageBinaryLicense,
369                                           True)
370
371    #
372    # Generate PACKAGE_UNI_FILE for the Package
373    #
374    FileHeader = GenHeaderCommentSection(PackageAbstract, PackageDescription, PackageCopyright, PackageLicense, False, \
375                                         TAB_COMMENT_EDK1_SPLIT)
376    GenPackageUNIEncodeFile(Package, FileHeader)
377
378    #
379    # for each section, maintain a dict, sorted arch will be its key,
380    #statement list will be its data
381    # { 'Arch1 Arch2 Arch3': [statement1, statement2],
382    #   'Arch1' : [statement1, statement3]
383    #  }
384    #
385
386    #
387    # generate [Defines] section
388    #
389    LeftOffset = 31
390    NewSectionDict = {TAB_ARCH_COMMON : []}
391    SpecialItemList = []
392
393    Statement = (u'%s ' % TAB_DEC_DEFINES_DEC_SPECIFICATION).ljust(LeftOffset) + u'= %s' % '0x00010017'
394    SpecialItemList.append(Statement)
395
396    BaseName = Package.GetBaseName()
397    if BaseName.startswith('.') or BaseName.startswith('-'):
398        BaseName = '_' + BaseName
399    Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_NAME).ljust(LeftOffset) + u'= %s' % BaseName
400    SpecialItemList.append(Statement)
401
402    Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_VERSION).ljust(LeftOffset) + u'= %s' % Package.GetVersion()
403    SpecialItemList.append(Statement)
404
405    Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_GUID).ljust(LeftOffset) + u'= %s' % Package.GetGuid()
406    SpecialItemList.append(Statement)
407
408    if Package.UNIFlag:
409        Statement = (u'%s ' % TAB_DEC_DEFINES_PKG_UNI_FILE).ljust(LeftOffset) + u'= %s' % Package.GetBaseName() + '.uni'
410        SpecialItemList.append(Statement)
411
412    for SortedArch in NewSectionDict:
413        NewSectionDict[SortedArch] = \
414        NewSectionDict[SortedArch] + SpecialItemList
415    Content += GenSection('Defines', NewSectionDict)
416
417    #
418    # generate [Includes] section
419    #
420    NewSectionDict = {}
421    IncludeArchList = Package.GetIncludeArchList()
422    if IncludeArchList:
423        for Path, ArchList in IncludeArchList:
424            Statement = Path
425            ArchList.sort()
426            SortedArch = ' '.join(ArchList)
427            if SortedArch in NewSectionDict:
428                NewSectionDict[SortedArch] = \
429                NewSectionDict[SortedArch] + [ConvertPath(Statement)]
430            else:
431                NewSectionDict[SortedArch] = [ConvertPath(Statement)]
432
433    Content += GenSection('Includes', NewSectionDict)
434
435    #
436    # generate [guids][protocols][ppis] sections
437    #
438    Content = GenGuidProtocolPpi(Package, Content)
439
440    #
441    # generate [LibraryClasses] section
442    #
443    NewSectionDict = {}
444    for LibraryClass in Package.GetLibraryClassList():
445        #
446        # Generate generic comment
447        #
448        HelpTextList = LibraryClass.GetHelpTextList()
449        HelpStr = _GetHelpStr(HelpTextList)
450        if HelpStr:
451            HelpStr = '@libraryclass' + HelpStr
452        CommentStr = GenGenericCommentF(HelpStr, 2, False, True)
453
454        Statement = CommentStr
455        Name = LibraryClass.GetLibraryClass()
456        IncludeHeader = LibraryClass.GetIncludeHeader()
457        Statement += Name + '|' + ConvertPath(IncludeHeader)
458        #
459        # generate tail comment
460        #
461        if LibraryClass.GetSupModuleList():
462            Statement += \
463            GenDecTailComment(LibraryClass.GetSupModuleList())
464        ArchList = LibraryClass.GetSupArchList()
465        ArchList.sort()
466        SortedArch = ' '.join(ArchList)
467        if SortedArch in NewSectionDict:
468            NewSectionDict[SortedArch] = \
469            NewSectionDict[SortedArch] + [Statement]
470        else:
471            NewSectionDict[SortedArch] = [Statement]
472
473    Content += GenSection('LibraryClasses', NewSectionDict, True, True)
474
475    #
476    # Generate '# [Error.<TokenSpcCName>]' section
477    #
478    Content = GenPcdErrorMsgSection(Package, Content)
479
480    Content = GenPcd(Package, Content)
481
482    #
483    # generate [UserExtensions] section
484    #
485    NewSectionDict = {}
486    for UserExtension in Package.GetUserExtensionList():
487        if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID and \
488            UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
489            continue
490        Statement = UserExtension.GetStatement()
491        if not Statement:
492            continue
493        else:
494            LineList = Statement.split('\n')
495            NewStatement = ""
496            for Line in LineList:
497                NewStatement += "  %s\n" % Line
498
499        SectionList = []
500        SectionName = 'UserExtensions'
501        UserId = UserExtension.GetUserID()
502        if UserId:
503            if '.' in UserId:
504                UserId = '"' + UserId + '"'
505            SectionName += '.' + UserId
506            if UserExtension.GetIdentifier():
507                SectionName += '.' + '"' + UserExtension.GetIdentifier() + '"'
508        if not UserExtension.GetSupArchList():
509            SectionList.append(SectionName)
510        else:
511            for Arch in UserExtension.GetSupArchList():
512                SectionList.append(SectionName + '.' + Arch)
513        SectionName = ', '.join(SectionList)
514        SectionName = ''.join(['[', SectionName, ']\n'])
515        Content += '\n' + SectionName + NewStatement
516
517    SaveFileOnChange(ContainerFile, Content, False)
518    if DistHeader.ReadOnly:
519        os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
520    else:
521        os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH)
522    return ContainerFile
523
524## GenPackageUNIEncodeFile
525# GenPackageUNIEncodeFile, default is a UCS-2LE encode file
526#
527def GenPackageUNIEncodeFile(PackageObject, UniFileHeader = '', Encoding=TAB_ENCODING_UTF16LE):
528    GenUNIFlag = False
529    OnlyLANGUAGE_EN_X = True
530    BinaryAbstract = []
531    BinaryDescription = []
532    #
533    # If more than one language code is used for any element that would be present in the PACKAGE_UNI_FILE,
534    # then the PACKAGE_UNI_FILE must be created.
535    #
536    for (Key, Value) in PackageObject.GetAbstract() + PackageObject.GetDescription():
537        if Key == TAB_LANGUAGE_EN_X:
538            GenUNIFlag = True
539        else:
540            OnlyLANGUAGE_EN_X = False
541
542    for UserExtension in PackageObject.GetUserExtensionList():
543        if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID \
544        and UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER:
545            for (Key, Value) in UserExtension.GetBinaryAbstract():
546                if Key == TAB_LANGUAGE_EN_X:
547                    GenUNIFlag = True
548                else:
549                    OnlyLANGUAGE_EN_X = False
550                BinaryAbstract.append((Key, Value))
551
552            for (Key, Value) in UserExtension.GetBinaryDescription():
553                if Key == TAB_LANGUAGE_EN_X:
554                    GenUNIFlag = True
555                else:
556                    OnlyLANGUAGE_EN_X = False
557                BinaryDescription.append((Key, Value))
558
559    for Pcd in PackageObject.GetPcdList():
560        for TxtObj in Pcd.GetPromptList() + Pcd.GetHelpTextList():
561            if TxtObj.GetLang() == TAB_LANGUAGE_EN_X:
562                GenUNIFlag = True
563            else:
564                OnlyLANGUAGE_EN_X = False
565
566        for PcdError in Pcd.GetPcdErrorsList():
567            if PcdError.GetErrorNumber().startswith('0x') or PcdError.GetErrorNumber().startswith('0X'):
568                for (Key, Value) in PcdError.GetErrorMessageList():
569                    if Key == TAB_LANGUAGE_EN_X:
570                        GenUNIFlag = True
571                    else:
572                        OnlyLANGUAGE_EN_X = False
573    if not GenUNIFlag:
574        return
575    elif OnlyLANGUAGE_EN_X:
576        return
577    else:
578        PackageObject.UNIFlag = True
579
580    if not os.path.exists(os.path.dirname(PackageObject.GetFullPath())):
581        os.makedirs(os.path.dirname(PackageObject.GetFullPath()))
582    ContainerFile = os.path.normpath(os.path.join(os.path.dirname(PackageObject.GetFullPath()),
583                                                  (PackageObject.GetBaseName() + '.uni')))
584
585    Content = UniFileHeader + '\r\n'
586    Content += '\r\n'
587
588    Content += FormatUniEntry('#string ' + TAB_DEC_PACKAGE_ABSTRACT, PackageObject.GetAbstract(), ContainerFile) + '\r\n'
589
590    Content += FormatUniEntry('#string ' + TAB_DEC_PACKAGE_DESCRIPTION, PackageObject.GetDescription(), ContainerFile) \
591    + '\r\n'
592
593    Content += FormatUniEntry('#string ' + TAB_DEC_BINARY_ABSTRACT, BinaryAbstract, ContainerFile) + '\r\n'
594
595    Content += FormatUniEntry('#string ' + TAB_DEC_BINARY_DESCRIPTION, BinaryDescription, ContainerFile) + '\r\n'
596
597    PromptGenList = []
598    HelpTextGenList = []
599    for Pcd in PackageObject.GetPcdList():
600        # Generate Prompt for each Pcd
601        PcdPromptStrName = '#string ' + 'STR_' + Pcd.GetTokenSpaceGuidCName() + '_' + Pcd.GetCName() + '_PROMPT '
602        TokenValueList = []
603        for TxtObj in Pcd.GetPromptList():
604            Lang = TxtObj.GetLang()
605            PromptStr = TxtObj.GetString()
606            #
607            # Avoid generating the same PROMPT entry more than one time.
608            #
609            if (PcdPromptStrName, Lang) not in PromptGenList:
610                TokenValueList.append((Lang, PromptStr))
611                PromptGenList.append((PcdPromptStrName, Lang))
612        PromptString = FormatUniEntry(PcdPromptStrName, TokenValueList, ContainerFile) + '\r\n'
613        if PromptString not in Content:
614            Content += PromptString
615
616        # Generate Help String for each Pcd
617        PcdHelpStrName = '#string ' + 'STR_' + Pcd.GetTokenSpaceGuidCName() + '_' + Pcd.GetCName() + '_HELP '
618        TokenValueList = []
619        for TxtObj in Pcd.GetHelpTextList():
620            Lang = TxtObj.GetLang()
621            HelpStr = TxtObj.GetString()
622            #
623            # Avoid generating the same HELP entry more than one time.
624            #
625            if (PcdHelpStrName, Lang) not in HelpTextGenList:
626                TokenValueList.append((Lang, HelpStr))
627                HelpTextGenList.append((PcdHelpStrName, Lang))
628        HelpTextString = FormatUniEntry(PcdHelpStrName, TokenValueList, ContainerFile) + '\r\n'
629        if HelpTextString not in Content:
630            Content += HelpTextString
631
632        # Generate PcdError for each Pcd if ErrorNo exist.
633        for PcdError in Pcd.GetPcdErrorsList():
634            ErrorNo = PcdError.GetErrorNumber()
635            if ErrorNo.startswith(TAB_HEX_START) or ErrorNo.startswith(TAB_CAPHEX_START):
636                PcdErrStrName = '#string ' + TAB_STR_TOKENCNAME + TAB_UNDERLINE_SPLIT + Pcd.GetTokenSpaceGuidCName() \
637                    + TAB_UNDERLINE_SPLIT + TAB_STR_TOKENERR \
638                    + TAB_UNDERLINE_SPLIT + ErrorNo[2:]
639                PcdErrString = FormatUniEntry(PcdErrStrName, PcdError.GetErrorMessageList(), ContainerFile) + '\r\n'
640                if PcdErrString not in Content:
641                    Content += PcdErrString
642
643    File = codecs.open(ContainerFile, 'w', Encoding)
644    File.write(u'\uFEFF' + Content)
645    File.stream.close()
646    Md5Sigature = md5.new(__FileHookOpen__(str(ContainerFile), 'rb').read())
647    Md5Sum = Md5Sigature.hexdigest()
648    if (ContainerFile, Md5Sum) not in PackageObject.FileList:
649        PackageObject.FileList.append((ContainerFile, Md5Sum))
650
651    return ContainerFile
652
653## GenPcdErrComment
654#
655#  @param PcdErrObject:  PcdErrorObject
656#
657#  @retval CommentStr:   Generated comment lines, with prefix "#"
658#
659def GenPcdErrComment (PcdErrObject):
660    CommentStr = ''
661    ErrorCode = PcdErrObject.GetErrorNumber()
662    ValidValueRange = PcdErrObject.GetValidValueRange()
663    if ValidValueRange:
664        CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_VALIDRANGE + TAB_SPACE_SPLIT
665        if ErrorCode:
666            CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
667        CommentStr += ValidValueRange + END_OF_LINE
668
669    ValidValue = PcdErrObject.GetValidValue()
670    if ValidValue:
671        ValidValueList = \
672        [Value for Value in ValidValue.split(TAB_SPACE_SPLIT) if Value]
673        CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_VALIDLIST + TAB_SPACE_SPLIT
674        if ErrorCode:
675            CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
676        CommentStr += TAB_COMMA_SPLIT.join(ValidValueList) + END_OF_LINE
677
678    Expression = PcdErrObject.GetExpression()
679    if Expression:
680        CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_EXPRESSION + TAB_SPACE_SPLIT
681        if ErrorCode:
682            CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT
683        CommentStr += Expression + END_OF_LINE
684
685    return CommentStr
686
687