1## @file
2# This file contained the parser for [Pcds] 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'''
9InfPcdSectionParser
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.Parsing import MacroParser
21from Library.Misc import GetSplitValueList
22from Library import GlobalData
23from Library.StringUtils import SplitPcdEntry
24from Parser.InfParserMisc import InfParserSectionRoot
25
26class InfPcdSectionParser(InfParserSectionRoot):
27    ## Section PCD related parser
28    #
29    # For 5 types of PCD list below, all use this function.
30    # 'FixedPcd', 'FeaturePcd', 'PatchPcd', 'Pcd', 'PcdEx'
31    #
32    # This is a INF independent parser, the validation in this parser only
33    # cover
34    # INF spec scope, will not cross DEC/DSC to check pcd value
35    #
36    def InfPcdParser(self, SectionString, InfSectionObject, FileName):
37        KeysList = []
38        PcdList   = []
39        CommentsList = []
40        ValueList = []
41        #
42        # Current section archs
43        #
44        LineIndex = -1
45        for Item in self.LastSectionHeaderContent:
46            if (Item[0], Item[1], Item[3]) not in KeysList:
47                KeysList.append((Item[0], Item[1], Item[3]))
48                LineIndex = Item[3]
49
50            if (Item[0].upper() == DT.TAB_INF_FIXED_PCD.upper() or \
51                Item[0].upper() == DT.TAB_INF_FEATURE_PCD.upper() or \
52                Item[0].upper() == DT.TAB_INF_PCD.upper()) and GlobalData.gIS_BINARY_INF:
53                Logger.Error('InfParser', FORMAT_INVALID, ST.ERR_ASBUILD_PCD_SECTION_TYPE%("\"" + Item[0] + "\""),
54                             File=FileName, Line=LineIndex)
55
56        #
57        # For Common INF file
58        #
59        if not GlobalData.gIS_BINARY_INF:
60            #
61            # Macro defined in this section
62            #
63            SectionMacros = {}
64            for Line in SectionString:
65                PcdLineContent = Line[0]
66                PcdLineNo      = Line[1]
67                if PcdLineContent.strip() == '':
68                    CommentsList = []
69                    continue
70
71                if PcdLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
72                    CommentsList.append(Line)
73                    continue
74                else:
75                    #
76                    # Encounter a PCD entry
77                    #
78                    if PcdLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
79                        CommentsList.append((
80                                PcdLineContent[PcdLineContent.find(DT.TAB_COMMENT_SPLIT):],
81                                PcdLineNo))
82                        PcdLineContent = PcdLineContent[:PcdLineContent.find(DT.TAB_COMMENT_SPLIT)]
83
84                if PcdLineContent != '':
85                    #
86                    # Find Macro
87                    #
88                    Name, Value = MacroParser((PcdLineContent, PcdLineNo),
89                                              FileName,
90                                              DT.MODEL_EFI_PCD,
91                                              self.FileLocalMacros)
92                    if Name is not None:
93                        SectionMacros[Name] = Value
94                        ValueList = []
95                        CommentsList = []
96                        continue
97
98                    PcdEntryReturn = SplitPcdEntry(PcdLineContent)
99
100                    if not PcdEntryReturn[1]:
101                        TokenList = ['']
102                    else:
103                        TokenList = PcdEntryReturn[0]
104
105                    ValueList[0:len(TokenList)] = TokenList
106
107                    #
108                    # Replace with Local section Macro and [Defines] section Macro.
109                    #
110                    ValueList = [InfExpandMacro(Value, (FileName, PcdLineContent, PcdLineNo),
111                                                self.FileLocalMacros, SectionMacros, True)
112                                for Value in ValueList]
113
114                if len(ValueList) >= 1:
115                    PcdList.append((ValueList, CommentsList, (PcdLineContent, PcdLineNo, FileName)))
116                    ValueList = []
117                    CommentsList = []
118                continue
119        #
120        # For Binary INF file
121        #
122        else:
123            for Line in SectionString:
124                LineContent = Line[0].strip()
125                LineNo      = Line[1]
126
127                if LineContent == '':
128                    CommentsList = []
129                    continue
130
131                if LineContent.startswith(DT.TAB_COMMENT_SPLIT):
132                    CommentsList.append(LineContent)
133                    continue
134                #
135                # Have comments at tail.
136                #
137                CommentIndex = LineContent.find(DT.TAB_COMMENT_SPLIT)
138                if  CommentIndex > -1:
139                    CommentsList.append(LineContent[CommentIndex+1:])
140                    LineContent = LineContent[:CommentIndex]
141
142                TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT)
143                #
144                # PatchablePcd
145                # TokenSpace.CName | Value | Offset
146                #
147                if KeysList[0][0].upper() == DT.TAB_INF_PATCH_PCD.upper():
148                    if len(TokenList) != 3:
149                        Logger.Error('InfParser',
150                                     FORMAT_INVALID,
151                                     ST.ERR_ASBUILD_PATCHPCD_FORMAT_INVALID,
152                                     File=FileName,
153                                     Line=LineNo,
154                                     ExtraData=LineContent)
155                #
156                elif KeysList[0][0].upper() == DT.TAB_INF_PCD_EX.upper():
157                    if len(TokenList) != 1:
158                        Logger.Error('InfParser',
159                                     FORMAT_INVALID,
160                                     ST.ERR_ASBUILD_PCDEX_FORMAT_INVALID,
161                                     File=FileName,
162                                     Line=LineNo,
163                                     ExtraData=LineContent)
164                ValueList[0:len(TokenList)] = TokenList
165                if len(ValueList) >= 1:
166                    PcdList.append((ValueList, CommentsList, (LineContent, LineNo, FileName)))
167                    ValueList = []
168                    CommentsList = []
169                continue
170
171        if not InfSectionObject.SetPcds(PcdList, KeysList = KeysList,
172                                        PackageInfo = self.InfPackageSection.GetPackages()):
173            Logger.Error('InfParser',
174                         FORMAT_INVALID,
175                         ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[PCD]"),
176                         File=FileName,
177                         Line=LineIndex)
178
179