1## @file
2# This file contained the parser for [Guids], [Ppis], [Protocols] sections in INF file
3#
4# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5#
6# SPDX-License-Identifier: BSD-2-Clause-Patent
7#
8'''
9InfGuidPpiProtocolSectionParser
10'''
11##
12# Import Modules
13#
14
15import Logger.Log as Logger
16from Logger import StringTable as ST
17from Logger.ToolError import FORMAT_INVALID
18from Parser.InfParserMisc import InfExpandMacro
19from Library import DataType as DT
20from Library import GlobalData
21from Library.Parsing import MacroParser
22from Library.Misc import GetSplitValueList
23from Library.ParserValidate import IsValidIdString
24from Library.ParserValidate import IsValidUserId
25from Library.ParserValidate import IsValidArch
26from Parser.InfParserMisc import InfParserSectionRoot
27
28class InfGuidPpiProtocolSectionParser(InfParserSectionRoot):
29    ## InfGuidParser
30    #
31    #
32    def InfGuidParser(self, SectionString, InfSectionObject, FileName):
33        #
34        # Macro defined in this section
35        #
36        SectionMacros = {}
37        ValueList = []
38        GuidList = []
39        CommentsList = []
40        CurrentLineVar = None
41        #
42        # Parse section content
43        #
44        for Line in SectionString:
45            LineContent = Line[0]
46            LineNo = Line[1]
47
48            if LineContent.strip() == '':
49                CommentsList = []
50                continue
51
52            if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
53                CommentsList.append(Line)
54                continue
55            else:
56                #
57                # Encounter a GUID entry
58                #
59                if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
60                    CommentsList.append((
61                            LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
62                            LineNo))
63                    LineContent = \
64                            LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
65
66            if LineContent != '':
67                #
68                # Find Macro
69                #
70                Name, Value = MacroParser((LineContent, LineNo),
71                                          FileName,
72                                          DT.MODEL_EFI_GUID,
73                                          self.FileLocalMacros)
74                if Name is not None:
75                    SectionMacros[Name] = Value
76                    CommentsList = []
77                    ValueList = []
78                    continue
79
80                TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
81                ValueList[0:len(TokenList)] = TokenList
82
83                #
84                # Replace with Local section Macro and [Defines] section Macro.
85                #
86                ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo),
87                                            self.FileLocalMacros, SectionMacros, True)
88                            for Value in ValueList]
89
90                CurrentLineVar = (LineContent, LineNo, FileName)
91
92
93            if len(ValueList) >= 1:
94                GuidList.append((ValueList, CommentsList, CurrentLineVar))
95                CommentsList = []
96                ValueList = []
97            continue
98
99        #
100        # Current section archs
101        #
102        ArchList = []
103        LineIndex = -1
104        for Item in self.LastSectionHeaderContent:
105            LineIndex = Item[3]
106            if Item[1] not in ArchList:
107                ArchList.append(Item[1])
108
109        if not InfSectionObject.SetGuid(GuidList, Arch=ArchList):
110            Logger.Error('InfParser',
111                         FORMAT_INVALID,
112                         ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Guid]"),
113                         File=FileName,
114                         Line=LineIndex)
115
116    ## InfPpiParser
117    #
118    #
119    def InfPpiParser(self, SectionString, InfSectionObject, FileName):
120        #
121        # Macro defined in this section
122        #
123        SectionMacros = {}
124        ValueList = []
125        PpiList = []
126        CommentsList = []
127        CurrentLineVar = None
128        #
129        # Parse section content
130        #
131        for Line in SectionString:
132            LineContent = Line[0]
133            LineNo = Line[1]
134
135            if LineContent.strip() == '':
136                CommentsList = []
137                continue
138
139            if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
140                CommentsList.append(Line)
141                continue
142            else:
143                #
144                # Encounter a PPI entry
145                #
146                if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
147                    CommentsList.append((
148                            LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
149                            LineNo))
150                    LineContent = \
151                            LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
152
153            if LineContent != '':
154                #
155                # Find Macro
156                #
157                Name, Value = MacroParser((LineContent, LineNo),
158                                          FileName,
159                                          DT.MODEL_EFI_PPI,
160                                          self.FileLocalMacros)
161                if Name is not None:
162                    SectionMacros[Name] = Value
163                    ValueList = []
164                    CommentsList = []
165                    continue
166
167                TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
168                ValueList[0:len(TokenList)] = TokenList
169
170                #
171                # Replace with Local section Macro and [Defines] section Macro.
172                #
173                ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), self.FileLocalMacros, SectionMacros)
174                            for Value in ValueList]
175
176                CurrentLineVar = (LineContent, LineNo, FileName)
177
178            if len(ValueList) >= 1:
179                PpiList.append((ValueList, CommentsList, CurrentLineVar))
180                ValueList = []
181                CommentsList = []
182            continue
183
184        #
185        # Current section archs
186        #
187        ArchList = []
188        LineIndex = -1
189        for Item in self.LastSectionHeaderContent:
190            LineIndex = Item[3]
191            if Item[1] not in ArchList:
192                ArchList.append(Item[1])
193
194        if not InfSectionObject.SetPpi(PpiList, Arch=ArchList):
195            Logger.Error('InfParser',
196                         FORMAT_INVALID,
197                         ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Ppis]"),
198                         File=FileName,
199                         Line=LineIndex)
200
201    ## InfUserExtensionParser
202    #
203    #
204    def InfUserExtensionParser(self, SectionString, InfSectionObject, FileName):
205
206        UserExtensionContent = ''
207
208        #
209        # Parse section content
210        #
211        for Line in SectionString:
212            LineContent = Line[0]
213
214# Comment the code to support user extension without any statement just the section header in []
215#             if LineContent.strip() == '':
216#                 continue
217
218            UserExtensionContent += LineContent + DT.END_OF_LINE
219            continue
220
221        #
222        # Current section UserId, IdString
223        #
224        IdContentList = []
225        LastItem = ''
226        SectionLineNo = None
227        for Item in self.LastSectionHeaderContent:
228            UserId = Item[1]
229            IdString = Item[2]
230            Arch = Item[3]
231            SectionLineNo = Item[4]
232            if not IsValidArch(Arch):
233                Logger.Error(
234                    'InfParser',
235                    FORMAT_INVALID,
236                    ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (Arch),
237                    File=GlobalData.gINF_MODULE_NAME,
238                    Line=SectionLineNo,
239                    ExtraData=None)
240
241            if (UserId, IdString, Arch) not in IdContentList:
242                #
243                # To check the UserId and IdString valid or not.
244                #
245                if not IsValidUserId(UserId):
246                    Logger.Error('InfParser',
247                                 FORMAT_INVALID,
248                                 ST.ERR_INF_PARSER_UE_SECTION_USER_ID_ERROR % (Item[1]),
249                                 File=GlobalData.gINF_MODULE_NAME,
250                                 Line=SectionLineNo,
251                                 ExtraData=None)
252
253                if not IsValidIdString(IdString):
254                    Logger.Error('InfParser',
255                                 FORMAT_INVALID,
256                                 ST.ERR_INF_PARSER_UE_SECTION_ID_STRING_ERROR % (IdString),
257                                 File=GlobalData.gINF_MODULE_NAME, Line=SectionLineNo,
258                                 ExtraData=None)
259                IdContentList.append((UserId, IdString, Arch))
260            else:
261                #
262                # Each UserExtensions section header must have a unique set
263                # of UserId, IdString and Arch values.
264                # This means that the same UserId can be used in more than one
265                # section header, provided the IdString or Arch values are
266                # different. The same IdString values can be used in more than
267                # one section header if the UserId or Arch values are
268                # different. The same UserId and the same IdString can be used
269                # in a section header if the Arch values are different in each
270                # of the section headers.
271                #
272                Logger.Error('InfParser',
273                             FORMAT_INVALID,
274                             ST.ERR_INF_PARSER_UE_SECTION_DUPLICATE_ERROR % (
275                                                                    IdString),
276                             File=GlobalData.gINF_MODULE_NAME,
277                             Line=SectionLineNo,
278                             ExtraData=None)
279            LastItem = Item
280
281        if not InfSectionObject.SetUserExtension(UserExtensionContent,
282                                                 IdContent=IdContentList,
283                                                 LineNo=SectionLineNo):
284            Logger.Error\
285            ('InfParser', FORMAT_INVALID, \
286             ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[UserExtension]"), \
287             File=FileName, Line=LastItem[4])
288
289    def InfProtocolParser(self, SectionString, InfSectionObject, FileName):
290        #
291        # Macro defined in this section
292        #
293        SectionMacros = {}
294        ValueList = []
295        ProtocolList = []
296        CommentsList = []
297        CurrentLineVar = None
298        #
299        # Parse section content
300        #
301        for Line in SectionString:
302            LineContent = Line[0]
303            LineNo = Line[1]
304
305            if LineContent.strip() == '':
306                CommentsList = []
307                continue
308
309            if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
310                CommentsList.append(Line)
311                continue
312            else:
313                #
314                # Encounter a Protocol entry
315                #
316                if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
317                    CommentsList.append((
318                            LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
319                            LineNo))
320                    LineContent = \
321                            LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
322
323            if LineContent != '':
324                #
325                # Find Macro
326                #
327                Name, Value = MacroParser((LineContent, LineNo),
328                                          FileName,
329                                          DT.MODEL_EFI_PROTOCOL,
330                                          self.FileLocalMacros)
331                if Name is not None:
332                    SectionMacros[Name] = Value
333                    ValueList = []
334                    CommentsList = []
335                    continue
336
337                TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
338                ValueList[0:len(TokenList)] = TokenList
339
340                #
341                # Replace with Local section Macro and [Defines] section Macro.
342                #
343                ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), self.FileLocalMacros, SectionMacros)
344                            for Value in ValueList]
345
346                CurrentLineVar = (LineContent, LineNo, FileName)
347
348            if len(ValueList) >= 1:
349                ProtocolList.append((ValueList, CommentsList, CurrentLineVar))
350                ValueList = []
351                CommentsList = []
352            continue
353
354        #
355        # Current section archs
356        #
357        ArchList = []
358        LineIndex = -1
359        for Item in self.LastSectionHeaderContent:
360            LineIndex = Item[3]
361            if Item[1] not in ArchList:
362                ArchList.append(Item[1])
363
364        if not InfSectionObject.SetProtocol(ProtocolList, Arch=ArchList):
365            Logger.Error\
366            ('InfParser', FORMAT_INVALID, \
367             ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Protocol]"), \
368             File=FileName, Line=LineIndex)
369