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