1## @file
2# This file is used to define class objects of INF file [Protocols] section.
3# It will consumed by InfParser.
4#
5# Copyright (c) 2011, 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'''
16InfProtocolObject
17'''
18
19from Library.ParserValidate import IsValidCVariableName
20from Library.CommentParsing import ParseComment
21from Library.ExpressionValidate import IsValidFeatureFlagExp
22
23from Library.Misc import Sdict
24
25from Object.Parser.InfMisc import ErrorInInf
26
27from Library import DataType as DT
28from Logger import StringTable as ST
29
30def ParseProtocolComment(CommentsList, InfProtocolItemObj):
31    CommentInsList = []
32    PreUsage = None
33    PreNotify = None
34    PreHelpText = ''
35    BlockFlag = -1
36    Count = 0
37    for CommentItem in CommentsList:
38        Count = Count + 1
39        CommentItemUsage, \
40        CommentItemNotify, \
41        CommentItemString, \
42        CommentItemHelpText = \
43                ParseComment(CommentItem,
44                             DT.PROTOCOL_USAGE_TOKENS,
45                             DT.PROTOCOL_NOTIFY_TOKENS,
46                             ['PROTOCOL'],
47                             False)
48
49        if CommentItemString:
50            pass
51
52        if CommentItemHelpText == None:
53            CommentItemHelpText = ''
54            if Count == len(CommentsList) and CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED:
55                CommentItemHelpText = DT.END_OF_LINE
56
57        if Count == len(CommentsList):
58            if BlockFlag == 1 or BlockFlag == 2:
59                if CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED:
60                    BlockFlag = 4
61                else:
62                    BlockFlag = 3
63            elif BlockFlag == -1:
64                BlockFlag = 4
65
66        if BlockFlag == -1 or BlockFlag == 1 or BlockFlag == 2:
67            if CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED:
68                if BlockFlag == -1:
69                    BlockFlag = 1
70                elif BlockFlag == 1:
71                    BlockFlag = 2
72            else:
73                if BlockFlag == 1 or BlockFlag == 2:
74                    BlockFlag = 3
75                elif BlockFlag == -1:
76                    BlockFlag = 4
77
78        #
79        # Combine two comment line if they are generic comment
80        #
81        if CommentItemUsage == CommentItemNotify == PreUsage == PreNotify == DT.ITEM_UNDEFINED:
82            CommentItemHelpText = PreHelpText + DT.END_OF_LINE + CommentItemHelpText
83
84            PreHelpText = CommentItemHelpText
85
86        if BlockFlag == 4:
87            CommentItemIns = InfProtocolItemCommentContent()
88            CommentItemIns.SetUsageItem(CommentItemUsage)
89            CommentItemIns.SetNotify(CommentItemNotify)
90            CommentItemIns.SetHelpStringItem(CommentItemHelpText)
91            CommentInsList.append(CommentItemIns)
92
93            BlockFlag = -1
94            PreUsage = None
95            PreNotify = None
96            PreHelpText = ''
97
98        elif BlockFlag == 3:
99            #
100            # Add previous help string
101            #
102            CommentItemIns = InfProtocolItemCommentContent()
103            CommentItemIns.SetUsageItem(DT.ITEM_UNDEFINED)
104            CommentItemIns.SetNotify(DT.ITEM_UNDEFINED)
105            if PreHelpText == '' or PreHelpText.endswith(DT.END_OF_LINE):
106                PreHelpText += DT.END_OF_LINE
107            CommentItemIns.SetHelpStringItem(PreHelpText)
108            CommentInsList.append(CommentItemIns)
109            #
110            # Add Current help string
111            #
112            CommentItemIns = InfProtocolItemCommentContent()
113            CommentItemIns.SetUsageItem(CommentItemUsage)
114            CommentItemIns.SetNotify(CommentItemNotify)
115            CommentItemIns.SetHelpStringItem(CommentItemHelpText)
116            CommentInsList.append(CommentItemIns)
117
118            BlockFlag = -1
119            PreUsage = None
120            PreNotify = None
121            PreHelpText = ''
122
123        else:
124            PreUsage = CommentItemUsage
125            PreNotify = CommentItemNotify
126            PreHelpText = CommentItemHelpText
127
128    InfProtocolItemObj.SetCommentList(CommentInsList)
129
130    return InfProtocolItemObj
131
132class InfProtocolItemCommentContent():
133    def __init__(self):
134        #
135        # ## SOMETIMES_CONSUMES ## HelpString
136        #
137        self.UsageItem = ''
138        #
139        # Help String
140        #
141        self.HelpStringItem = ''
142        self.Notify = ''
143        self.CommentList = []
144
145    def SetUsageItem(self, UsageItem):
146        self.UsageItem = UsageItem
147    def GetUsageItem(self):
148        return self.UsageItem
149
150    def SetNotify(self, Notify):
151        if Notify != DT.ITEM_UNDEFINED:
152            self.Notify = 'true'
153    def GetNotify(self):
154        return self.Notify
155
156    def SetHelpStringItem(self, HelpStringItem):
157        self.HelpStringItem = HelpStringItem
158    def GetHelpStringItem(self):
159        return self.HelpStringItem
160
161class InfProtocolItem():
162    def __init__(self):
163        self.Name = ''
164        self.FeatureFlagExp = ''
165        self.SupArchList = []
166        self.CommentList = []
167
168    def SetName(self, Name):
169        self.Name = Name
170    def GetName(self):
171        return self.Name
172
173    def SetFeatureFlagExp(self, FeatureFlagExp):
174        self.FeatureFlagExp = FeatureFlagExp
175    def GetFeatureFlagExp(self):
176        return self.FeatureFlagExp
177
178    def SetSupArchList(self, SupArchList):
179        self.SupArchList = SupArchList
180    def GetSupArchList(self):
181        return self.SupArchList
182
183    def SetCommentList(self, CommentList):
184        self.CommentList = CommentList
185    def GetCommentList(self):
186        return self.CommentList
187
188##
189#
190#
191#
192class InfProtocolObject():
193    def __init__(self):
194        self.Protocols = Sdict()
195        #
196        # Macro defined in this section should be only used in this section.
197        #
198        self.Macros = {}
199
200    def SetProtocol(self, ProtocolContent, Arch = None,):
201        __SupArchList = []
202        for ArchItem in Arch:
203            #
204            # Validate Arch
205            #
206            if (ArchItem == '' or ArchItem == None):
207                ArchItem = 'COMMON'
208            __SupArchList.append(ArchItem)
209
210        for Item in ProtocolContent:
211            #
212            # Get Comment content of this protocol
213            #
214            CommentsList = None
215            if len(Item) == 3:
216                CommentsList = Item[1]
217            CurrentLineOfItem = Item[2]
218            LineInfo = (CurrentLineOfItem[2], CurrentLineOfItem[1], CurrentLineOfItem[0])
219            Item = Item[0]
220            InfProtocolItemObj = InfProtocolItem()
221            if len(Item) >= 1 and len(Item) <= 2:
222                #
223                # Only CName contained
224                #
225                if not IsValidCVariableName(Item[0]):
226                    ErrorInInf(ST.ERR_INF_PARSER_INVALID_CNAME%(Item[0]),
227                               LineInfo=LineInfo)
228                if (Item[0] != ''):
229                    InfProtocolItemObj.SetName(Item[0])
230                else:
231                    ErrorInInf(ST.ERR_INF_PARSER_CNAME_MISSING,
232                               LineInfo=LineInfo)
233            if len(Item) == 2:
234                #
235                # Contained CName and Feature Flag Express
236                # <statements>           ::=  <CName> ["|"
237                # <FeatureFlagExpress>]
238                # For Protocol Object
239                #
240                if Item[1].strip() == '':
241                    ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING,
242                               LineInfo=LineInfo)
243                #
244                # Validate Feature Flag Express for Item[1]
245                #
246                FeatureFlagRtv = IsValidFeatureFlagExp(Item[1].strip())
247                if not FeatureFlagRtv[0]:
248                    ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]),
249                               LineInfo=LineInfo)
250                InfProtocolItemObj.SetFeatureFlagExp(Item[1])
251
252            if len(Item) < 1 or len(Item) > 2:
253                #
254                # Invalid format of Protocols statement
255                #
256                ErrorInInf(ST.ERR_INF_PARSER_GUID_PPI_PROTOCOL_SECTION_CONTENT_ERROR,
257                           LineInfo=LineInfo)
258
259            #
260            # Get/Set Usage and HelpString for Protocol entry
261            #
262            if CommentsList != None and len(CommentsList) != 0:
263                InfProtocolItemObj = ParseProtocolComment(CommentsList, InfProtocolItemObj)
264            else:
265                CommentItemIns = InfProtocolItemCommentContent()
266                CommentItemIns.SetUsageItem(DT.ITEM_UNDEFINED)
267                CommentItemIns.SetNotify(DT.ITEM_UNDEFINED)
268                InfProtocolItemObj.SetCommentList([CommentItemIns])
269
270            InfProtocolItemObj.SetSupArchList(__SupArchList)
271
272            #
273            # Determine protocol name duplicate. Follow below rule:
274            #
275            # A protocol must not be duplicated within a [Protocols] section.
276            # A protocol may appear in multiple architectural [Protocols]
277            # sections. A protocol listed in an architectural [Protocols]
278            # section must not be listed in the common architectural
279            # [Protocols] section.
280            #
281            # NOTE: This check will not report error now.
282            #
283            for Item in self.Protocols:
284                if Item.GetName() == InfProtocolItemObj.GetName():
285                    ItemSupArchList = Item.GetSupArchList()
286                    for ItemArch in ItemSupArchList:
287                        for ProtocolItemObjArch in __SupArchList:
288                            if ItemArch == ProtocolItemObjArch:
289                                #
290                                # ST.ERR_INF_PARSER_ITEM_DUPLICATE
291                                #
292                                pass
293                            if ItemArch.upper() == 'COMMON' or ProtocolItemObjArch.upper() == 'COMMON':
294                                #
295                                # ST.ERR_INF_PARSER_ITEM_DUPLICATE_COMMON
296                                #
297                                pass
298
299            if self.Protocols.has_key((InfProtocolItemObj)):
300                ProcotolList = self.Protocols[InfProtocolItemObj]
301                ProcotolList.append(InfProtocolItemObj)
302                self.Protocols[InfProtocolItemObj] = ProcotolList
303            else:
304                ProcotolList = []
305                ProcotolList.append(InfProtocolItemObj)
306                self.Protocols[InfProtocolItemObj] = ProcotolList
307
308        return True
309
310    def GetProtocol(self):
311        return self.Protocols
312