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