1## @file
2# This file contained the parser for BuildOption 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
9'''
10InfBuildOptionSectionParser
11'''
12##
13# Import Modules
14#
15from Library import DataType as DT
16from Library import GlobalData
17import Logger.Log as Logger
18from Logger import StringTable as ST
19from Logger.ToolError import FORMAT_INVALID
20from Parser.InfParserMisc import InfExpandMacro
21from Library.Misc import GetSplitValueList
22from Parser.InfParserMisc import IsAsBuildOptionInfo
23from Library.Misc import GetHelpStringByRemoveHashKey
24from Library.ParserValidate import IsValidFamily
25from Library.ParserValidate import IsValidBuildOptionName
26from Parser.InfParserMisc import InfParserSectionRoot
27
28class InfBuildOptionSectionParser(InfParserSectionRoot):
29    ## InfBuildOptionParser
30    #
31    #
32    def InfBuildOptionParser(self, SectionString, InfSectionObject, FileName):
33
34        BuildOptionList = []
35        SectionContent  = ''
36
37        if not GlobalData.gIS_BINARY_INF:
38            ValueList       = []
39            LineNo          = 0
40
41            for Line in SectionString:
42                LineContent = Line[0]
43                LineNo      = Line[1]
44                TailComments = ''
45                ReplaceFlag = False
46
47                if LineContent.strip() == '':
48                    SectionContent += LineContent + DT.END_OF_LINE
49                    continue
50                #
51                # Found Comment
52                #
53                if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
54                    SectionContent += LineContent + DT.END_OF_LINE
55                    continue
56
57                #
58                # Find Tail comment.
59                #
60                if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
61                    TailComments = LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):]
62                    LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
63
64                TokenList = GetSplitValueList(LineContent, DT.TAB_DEQUAL_SPLIT, 1)
65                if len(TokenList) == 2:
66                    #
67                    # "Replace" type build option
68                    #
69                    TokenList.append('True')
70                    ReplaceFlag = True
71                else:
72                    TokenList = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)
73                    #
74                    # "Append" type build option
75                    #
76                    if len(TokenList) == 2:
77                        TokenList.append('False')
78                    else:
79                        Logger.Error('InfParser',
80                                     FORMAT_INVALID,
81                                     ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
82                                     ExtraData=LineContent,
83                                     File=FileName,
84                                     Line=LineNo)
85
86                ValueList[0:len(TokenList)] = TokenList
87
88                #
89                # Replace with [Defines] section Macro
90                #
91                ValueList[0] = InfExpandMacro(ValueList[0], (FileName, LineContent, LineNo),
92                                              self.FileLocalMacros, None)
93                ValueList[1] = InfExpandMacro(ValueList[1], (FileName, LineContent, LineNo),
94                                              self.FileLocalMacros, None, True)
95                EqualString = ''
96                if not ReplaceFlag:
97                    EqualString = ' = '
98                else:
99                    EqualString = ' == '
100
101                SectionContent += ValueList[0] + EqualString + ValueList[1] + TailComments + DT.END_OF_LINE
102
103                Family = GetSplitValueList(ValueList[0], DT.TAB_COLON_SPLIT, 1)
104                if len(Family) == 2:
105                    if not IsValidFamily(Family[0]):
106                        Logger.Error('InfParser',
107                                     FORMAT_INVALID,
108                                     ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
109                                     ExtraData=LineContent,
110                                     File=FileName,
111                                     Line=LineNo)
112                    if not IsValidBuildOptionName(Family[1]):
113                        Logger.Error('InfParser',
114                                     FORMAT_INVALID,
115                                     ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
116                                     ExtraData=LineContent,
117                                     File=FileName,
118                                     Line=LineNo)
119                if len(Family) == 1:
120                    if not IsValidBuildOptionName(Family[0]):
121                        Logger.Error('InfParser',
122                                     FORMAT_INVALID,
123                                     ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
124                                     ExtraData=LineContent,
125                                     File=FileName,
126                                     Line=LineNo)
127
128                BuildOptionList.append(ValueList)
129                ValueList = []
130                continue
131        else:
132            BuildOptionList = InfAsBuiltBuildOptionParser(SectionString, FileName)
133
134        #
135        # Current section archs
136        #
137        ArchList = []
138        LastItem = ''
139        for Item in self.LastSectionHeaderContent:
140            LastItem = Item
141            if not (Item[1] == '' or Item[1] == '') and Item[1] not in ArchList:
142                ArchList.append(Item[1])
143                InfSectionObject.SetSupArchList(Item[1])
144
145        InfSectionObject.SetAllContent(SectionContent)
146        if not InfSectionObject.SetBuildOptions(BuildOptionList, ArchList, SectionContent):
147            Logger.Error('InfParser',
148                         FORMAT_INVALID,
149                         ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[BuilOptions]"),
150                         File=FileName,
151                         Line=LastItem[3])
152
153## InfBuildOptionParser
154#
155#
156def InfAsBuiltBuildOptionParser(SectionString, FileName):
157    BuildOptionList = []
158    #
159    # AsBuild Binary INF file.
160    #
161    AsBuildOptionFlag = False
162    BuildOptionItem = []
163    Count = 0
164    for Line in SectionString:
165        Count += 1
166        LineContent = Line[0]
167        LineNo      = Line[1]
168
169        #
170        # The last line
171        #
172        if len(SectionString) == Count:
173            if LineContent.strip().startswith("##") and AsBuildOptionFlag:
174                BuildOptionList.append(BuildOptionItem)
175                BuildOptionList.append([GetHelpStringByRemoveHashKey(LineContent)])
176            elif LineContent.strip().startswith("#") and AsBuildOptionFlag:
177                BuildOptionInfo = GetHelpStringByRemoveHashKey(LineContent)
178                BuildOptionItem.append(BuildOptionInfo)
179                BuildOptionList.append(BuildOptionItem)
180            else:
181                if len(BuildOptionItem) > 0:
182                    BuildOptionList.append(BuildOptionItem)
183
184            break
185
186        if LineContent.strip() == '':
187            AsBuildOptionFlag = False
188            continue
189
190        if LineContent.strip().startswith("##") and AsBuildOptionFlag:
191            if len(BuildOptionItem) > 0:
192                BuildOptionList.append(BuildOptionItem)
193
194            BuildOptionItem = []
195
196        if not LineContent.strip().startswith("#"):
197            Logger.Error('InfParser',
198                        FORMAT_INVALID,
199                        ST.ERR_BO_CONTATIN_ASBUILD_AND_COMMON,
200                        File=FileName,
201                        Line=LineNo,
202                        ExtraData=LineContent)
203
204        if IsAsBuildOptionInfo(LineContent):
205            AsBuildOptionFlag = True
206            continue
207
208        if AsBuildOptionFlag:
209            BuildOptionInfo = GetHelpStringByRemoveHashKey(LineContent)
210            BuildOptionItem.append(BuildOptionInfo)
211
212    return BuildOptionList
213