]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools: Report Error if use SET in Dsc
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileParser.py
1 ## @file
2 # This file is used to parse meta files
3 #
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this 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
15 ##
16 # Import Modules
17 #
18 from __future__ import print_function
19 from __future__ import absolute_import
20 import Common.LongFilePathOs as os
21 import re
22 import time
23 import copy
24 from hashlib import md5
25
26 import Common.EdkLogger as EdkLogger
27 import Common.GlobalData as GlobalData
28
29 from CommonDataClass.DataClass import *
30 from Common.DataType import *
31 from Common.StringUtils import *
32 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue, StructPattern
33 from Common.Expression import *
34 from CommonDataClass.Exceptions import *
35 from Common.LongFilePathSupport import OpenLongFilePath as open
36 from collections import defaultdict
37 from .MetaFileTable import MetaFileStorage
38 from .MetaFileCommentParser import CheckInfComment
39 from Common.DataType import TAB_COMMENT_EDK_START, TAB_COMMENT_EDK_END
40
41 ## RegEx for finding file versions
42 hexVersionPattern = re.compile(r'0[xX][\da-f-A-F]{5,8}')
43 decVersionPattern = re.compile(r'\d+\.\d+')
44 CODEPattern = re.compile(r"{CODE\([a-fA-F0-9Xx\{\},\s]*\)}")
45
46 ## A decorator used to parse macro definition
47 def ParseMacro(Parser):
48 def MacroParser(self):
49 Match = GlobalData.gMacroDefPattern.match(self._CurrentLine)
50 if not Match:
51 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
52 Parser(self)
53 return
54
55 TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)
56 # Syntax check
57 if not TokenList[0]:
58 EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
59 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
60 if len(TokenList) < 2:
61 TokenList.append('')
62
63 Type = Match.group(1)
64 Name, Value = TokenList
65 # Global macros can be only defined via environment variable
66 if Name in GlobalData.gGlobalDefines:
67 EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
68 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
69 # Only upper case letters, digit and '_' are allowed
70 if not GlobalData.gMacroNamePattern.match(Name):
71 EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
72 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
73
74 Value = ReplaceMacro(Value, self._Macros)
75 if Type in self.DataType:
76 self._ItemType = self.DataType[Type]
77 else:
78 self._ItemType = MODEL_META_DATA_DEFINE
79 # DEFINE defined macros
80 if Type == TAB_DSC_DEFINES_DEFINE:
81 #
82 # First judge whether this DEFINE is in conditional directive statements or not.
83 #
84 if isinstance(self, DscParser) and self._InDirective > -1:
85 pass
86 else:
87 if isinstance(self, DecParser):
88 if MODEL_META_DATA_HEADER in self._SectionType:
89 self._FileLocalMacros[Name] = Value
90 else:
91 self._ConstructSectionMacroDict(Name, Value)
92 elif self._SectionType == MODEL_META_DATA_HEADER:
93 self._FileLocalMacros[Name] = Value
94 else:
95 self._ConstructSectionMacroDict(Name, Value)
96
97 # EDK_GLOBAL defined macros
98 elif not isinstance(self, DscParser):
99 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
100 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
101 elif self._SectionType != MODEL_META_DATA_HEADER:
102 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
103 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
104 elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
105 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
106 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
107
108 self._ValueList = [Type, Name, Value]
109
110 return MacroParser
111
112 ## Base class of parser
113 #
114 # This class is used for derivation purpose. The specific parser for one kind
115 # type file must derive this class and implement some public interfaces.
116 #
117 # @param FilePath The path of platform description file
118 # @param FileType The raw data of DSC file
119 # @param Table Database used to retrieve module/package information
120 # @param Macros Macros used for replacement in file
121 # @param Owner Owner ID (for sub-section parsing)
122 # @param From ID from which the data comes (for !INCLUDE directive)
123 #
124 class MetaFileParser(object):
125 # data type (file content) for specific file type
126 DataType = {}
127
128 # Parser objects used to implement singleton
129 MetaFiles = {}
130
131 ## Factory method
132 #
133 # One file, one parser object. This factory method makes sure that there's
134 # only one object constructed for one meta file.
135 #
136 # @param Class class object of real AutoGen class
137 # (InfParser, DecParser or DscParser)
138 # @param FilePath The path of meta file
139 # @param *args The specific class related parameters
140 # @param **kwargs The specific class related dict parameters
141 #
142 def __new__(Class, FilePath, *args, **kwargs):
143 if FilePath in Class.MetaFiles:
144 return Class.MetaFiles[FilePath]
145 else:
146 ParserObject = super(MetaFileParser, Class).__new__(Class)
147 Class.MetaFiles[FilePath] = ParserObject
148 return ParserObject
149
150 ## Constructor of MetaFileParser
151 #
152 # Initialize object of MetaFileParser
153 #
154 # @param FilePath The path of platform description file
155 # @param FileType The raw data of DSC file
156 # @param Arch Default Arch value for filtering sections
157 # @param Table Database used to retrieve module/package information
158 # @param Owner Owner ID (for sub-section parsing)
159 # @param From ID from which the data comes (for !INCLUDE directive)
160 #
161 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
162 self._Table = Table
163 self._RawTable = Table
164 self._Arch = Arch
165 self._FileType = FileType
166 self.MetaFile = FilePath
167 self._FileDir = self.MetaFile.Dir
168 self._Defines = {}
169 self._FileLocalMacros = {}
170 self._SectionsMacroDict = defaultdict(dict)
171
172 # for recursive parsing
173 self._Owner = [Owner]
174 self._From = From
175
176 # parsr status for parsing
177 self._ValueList = ['', '', '', '', '']
178 self._Scope = []
179 self._LineIndex = 0
180 self._CurrentLine = ''
181 self._SectionType = MODEL_UNKNOWN
182 self._SectionName = ''
183 self._InSubsection = False
184 self._SubsectionType = MODEL_UNKNOWN
185 self._SubsectionName = ''
186 self._ItemType = MODEL_UNKNOWN
187 self._LastItem = -1
188 self._Enabled = 0
189 self._Finished = False
190 self._PostProcessed = False
191 # Different version of meta-file has different way to parse.
192 self._Version = 0
193 self._GuidDict = {} # for Parser PCD value {GUID(gTokeSpaceGuidName)}
194
195 ## Store the parsed data in table
196 def _Store(self, *Args):
197 return self._Table.Insert(*Args)
198
199 ## Virtual method for starting parse
200 def Start(self):
201 raise NotImplementedError
202
203 ## Notify a post-process is needed
204 def DoPostProcess(self):
205 self._PostProcessed = False
206
207 ## Set parsing complete flag in both class and table
208 def _Done(self):
209 self._Finished = True
210 self._Table.SetEndFlag()
211
212 def _PostProcess(self):
213 self._PostProcessed = True
214
215 ## Get the parse complete flag
216 @property
217 def Finished(self):
218 return self._Finished
219
220 ## Set the complete flag
221 @Finished.setter
222 def Finished(self, Value):
223 self._Finished = Value
224
225 ## Remove records that do not match given Filter Arch
226 def _FilterRecordList(self, RecordList, FilterArch):
227 NewRecordList = []
228 for Record in RecordList:
229 Arch = Record[3]
230 if Arch == TAB_ARCH_COMMON or Arch == FilterArch:
231 NewRecordList.append(Record)
232 return NewRecordList
233
234 ## Use [] style to query data in table, just for readability
235 #
236 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
237 #
238 def __getitem__(self, DataInfo):
239 if not isinstance(DataInfo, type(())):
240 DataInfo = (DataInfo,)
241
242 # Parse the file first, if necessary
243 self.StartParse()
244
245 # No specific ARCH or Platform given, use raw data
246 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):
247 return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)
248
249 # Do post-process if necessary
250 if not self._PostProcessed:
251 self._PostProcess()
252
253 return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])
254
255 def StartParse(self):
256 if not self._Finished:
257 if self._RawTable.IsIntegrity():
258 self._Finished = True
259 else:
260 self._Table = self._RawTable
261 self._PostProcessed = False
262 self.Start()
263 ## Data parser for the common format in different type of file
264 #
265 # The common format in the meatfile is like
266 #
267 # xxx1 | xxx2 | xxx3
268 #
269 @ParseMacro
270 def _CommonParser(self):
271 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
272 self._ValueList[0:len(TokenList)] = TokenList
273
274 ## Data parser for the format in which there's path
275 #
276 # Only path can have macro used. So we need to replace them before use.
277 #
278 @ParseMacro
279 def _PathParser(self):
280 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
281 self._ValueList[0:len(TokenList)] = TokenList
282 # Don't do macro replacement for dsc file at this point
283 if not isinstance(self, DscParser):
284 Macros = self._Macros
285 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
286
287 ## Skip unsupported data
288 def _Skip(self):
289 EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
290 Line=self._LineIndex + 1, ExtraData=self._CurrentLine);
291 self._ValueList[0:1] = [self._CurrentLine]
292
293 ## Skip unsupported data for UserExtension Section
294 def _SkipUserExtension(self):
295 self._ValueList[0:1] = [self._CurrentLine]
296
297 ## Section header parser
298 #
299 # The section header is always in following format:
300 #
301 # [section_name.arch<.platform|module_type>]
302 #
303 def _SectionHeaderParser(self):
304 self._Scope = []
305 self._SectionName = ''
306 ArchList = set()
307 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
308 if Item == '':
309 continue
310 ItemList = GetSplitValueList(Item, TAB_SPLIT, 3)
311 # different section should not mix in one section
312 if self._SectionName != '' and self._SectionName != ItemList[0].upper():
313 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
314 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
315 self._SectionName = ItemList[0].upper()
316 if self._SectionName in self.DataType:
317 self._SectionType = self.DataType[self._SectionName]
318 # Check if the section name is valid
319 if self._SectionName not in SECTIONS_HAVE_ITEM_AFTER_ARCH_SET and len(ItemList) > 3:
320 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
321 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
322 elif self._Version >= 0x00010005:
323 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
324 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
325 else:
326 self._SectionType = MODEL_UNKNOWN
327
328 # S1 is always Arch
329 if len(ItemList) > 1:
330 S1 = ItemList[1].upper()
331 else:
332 S1 = TAB_ARCH_COMMON
333 ArchList.add(S1)
334
335 # S2 may be Platform or ModuleType
336 if len(ItemList) > 2:
337 if self._SectionName.upper() in SECTIONS_HAVE_ITEM_PCD_SET:
338 S2 = ItemList[2]
339 else:
340 S2 = ItemList[2].upper()
341 else:
342 S2 = TAB_COMMON
343 if len(ItemList) > 3:
344 S3 = ItemList[3]
345 else:
346 S3 = TAB_COMMON
347 self._Scope.append([S1, S2, S3])
348
349 # 'COMMON' must not be used with specific ARCHs at the same section
350 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:
351 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
352 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
353 # If the section information is needed later, it should be stored in database
354 self._ValueList[0] = self._SectionName
355
356 ## [defines] section parser
357 @ParseMacro
358 def _DefineParser(self):
359 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
360 self._ValueList[1:len(TokenList)] = TokenList
361 if not self._ValueList[1]:
362 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
363 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
364 if not self._ValueList[2]:
365 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
366 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
367
368 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
369 Name, Value = self._ValueList[1], self._ValueList[2]
370 MacroUsed = GlobalData.gMacroRefPattern.findall(Value)
371 if len(MacroUsed) != 0:
372 for Macro in MacroUsed:
373 if Macro in GlobalData.gGlobalDefines:
374 EdkLogger.error("Parser", FORMAT_INVALID, "Global macro %s is not permitted." % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
375 else:
376 EdkLogger.error("Parser", FORMAT_INVALID, "%s not defined" % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
377 # Sometimes, we need to make differences between EDK and EDK2 modules
378 if Name == 'INF_VERSION':
379 if hexVersionPattern.match(Value):
380 self._Version = int(Value, 0)
381 elif decVersionPattern.match(Value):
382 ValueList = Value.split('.')
383 Major = int(ValueList[0], 0)
384 Minor = int(ValueList[1], 0)
385 if Major > 0xffff or Minor > 0xffff:
386 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
387 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
388 self._Version = int('0x{0:04x}{1:04x}'.format(Major, Minor), 0)
389 else:
390 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
391 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
392
393 if isinstance(self, InfParser) and self._Version < 0x00010005:
394 # EDK module allows using defines as macros
395 self._FileLocalMacros[Name] = Value
396 self._Defines[Name] = Value
397
398 ## [BuildOptions] section parser
399 @ParseMacro
400 def _BuildOptionParser(self):
401 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
402 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
403 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
404 if len(TokenList2) == 2:
405 self._ValueList[0] = TokenList2[0] # toolchain family
406 self._ValueList[1] = TokenList2[1] # keys
407 else:
408 self._ValueList[1] = TokenList[0]
409 if len(TokenList) == 2 and not isinstance(self, DscParser): # value
410 self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
411
412 if self._ValueList[1].count('_') != 4:
413 EdkLogger.error(
414 'Parser',
415 FORMAT_INVALID,
416 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
417 ExtraData=self._CurrentLine,
418 File=self.MetaFile,
419 Line=self._LineIndex + 1
420 )
421 def GetValidExpression(self, TokenSpaceGuid, PcdCName):
422 return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)
423
424 @property
425 def _Macros(self):
426 Macros = {}
427 Macros.update(self._FileLocalMacros)
428 Macros.update(self._GetApplicableSectionMacro())
429 return Macros
430
431 ## Construct section Macro dict
432 def _ConstructSectionMacroDict(self, Name, Value):
433 ScopeKey = [(Scope[0], Scope[1], Scope[2]) for Scope in self._Scope]
434 ScopeKey = tuple(ScopeKey)
435 #
436 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
437 # As Pcd section macro usage is not alllowed, so here it is safe
438 #
439 if isinstance(self, DecParser):
440 SectionDictKey = self._SectionType[0], ScopeKey
441 else:
442 SectionDictKey = self._SectionType, ScopeKey
443
444 self._SectionsMacroDict[SectionDictKey][Name] = Value
445
446 ## Get section Macros that are applicable to current line, which may come from other sections
447 ## that share the same name while scope is wider
448 def _GetApplicableSectionMacro(self):
449 Macros = {}
450
451 ComComMacroDict = {}
452 ComSpeMacroDict = {}
453 SpeSpeMacroDict = {}
454
455 ActiveSectionType = self._SectionType
456 if isinstance(self, DecParser):
457 ActiveSectionType = self._SectionType[0]
458
459 for (SectionType, Scope) in self._SectionsMacroDict:
460 if SectionType != ActiveSectionType:
461 continue
462
463 for ActiveScope in self._Scope:
464 Scope0, Scope1, Scope2= ActiveScope[0], ActiveScope[1], ActiveScope[2]
465 if(Scope0, Scope1, Scope2) not in Scope:
466 break
467 else:
468 SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
469
470 for ActiveScope in self._Scope:
471 Scope0, Scope1, Scope2 = ActiveScope[0], ActiveScope[1], ActiveScope[2]
472 if(Scope0, Scope1, Scope2) not in Scope and (Scope0, TAB_COMMON, TAB_COMMON) not in Scope and (TAB_COMMON, Scope1, TAB_COMMON) not in Scope:
473 break
474 else:
475 ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
476
477 if (TAB_COMMON, TAB_COMMON, TAB_COMMON) in Scope:
478 ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
479
480 Macros.update(ComComMacroDict)
481 Macros.update(ComSpeMacroDict)
482 Macros.update(SpeSpeMacroDict)
483
484 return Macros
485
486 _SectionParser = {}
487
488 ## INF file parser class
489 #
490 # @param FilePath The path of platform description file
491 # @param FileType The raw data of DSC file
492 # @param Table Database used to retrieve module/package information
493 # @param Macros Macros used for replacement in file
494 #
495 class InfParser(MetaFileParser):
496 # INF file supported data types (one type per section)
497 DataType = {
498 TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
499 TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
500 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
501 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
502 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
503 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
504 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
505 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
506 TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
507 TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
508 TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
509 TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
510 TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
511 TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
512 TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
513 TAB_GUIDS.upper() : MODEL_EFI_GUID,
514 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
515 TAB_PPIS.upper() : MODEL_EFI_PPI,
516 TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
517 TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
518 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
519 }
520
521 ## Constructor of InfParser
522 #
523 # Initialize object of InfParser
524 #
525 # @param FilePath The path of module description file
526 # @param FileType The raw data of DSC file
527 # @param Arch Default Arch value for filtering sections
528 # @param Table Database used to retrieve module/package information
529 #
530 def __init__(self, FilePath, FileType, Arch, Table):
531 # prevent re-initialization
532 if hasattr(self, "_Table"):
533 return
534 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)
535 self.PcdsDict = {}
536
537 ## Parser starter
538 def Start(self):
539 NmakeLine = ''
540 Content = ''
541 try:
542 Content = open(str(self.MetaFile), 'r').readlines()
543 except:
544 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
545
546 # parse the file line by line
547 IsFindBlockComment = False
548 GetHeaderComment = False
549 TailComments = []
550 SectionComments = []
551 Comments = []
552
553 for Index in range(0, len(Content)):
554 # skip empty, commented, block commented lines
555 Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)
556 NextLine = ''
557 if Index + 1 < len(Content):
558 NextLine, NextComment = CleanString2(Content[Index + 1])
559 if Line == '':
560 if Comment:
561 Comments.append((Comment, Index + 1))
562 elif GetHeaderComment:
563 SectionComments.extend(Comments)
564 Comments = []
565 continue
566 if Line.find(TAB_COMMENT_EDK_START) > -1:
567 IsFindBlockComment = True
568 continue
569 if Line.find(TAB_COMMENT_EDK_END) > -1:
570 IsFindBlockComment = False
571 continue
572 if IsFindBlockComment:
573 continue
574
575 self._LineIndex = Index
576 self._CurrentLine = Line
577
578 # section header
579 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
580 if not GetHeaderComment:
581 for Cmt, LNo in Comments:
582 self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', TAB_COMMON,
583 TAB_COMMON, self._Owner[-1], LNo, -1, LNo, -1, 0)
584 GetHeaderComment = True
585 else:
586 TailComments.extend(SectionComments + Comments)
587 Comments = []
588 self._SectionHeaderParser()
589 # Check invalid sections
590 if self._Version < 0x00010005:
591 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
592 MODEL_EFI_LIBRARY_CLASS,
593 MODEL_META_DATA_PACKAGE,
594 MODEL_PCD_FIXED_AT_BUILD,
595 MODEL_PCD_PATCHABLE_IN_MODULE,
596 MODEL_PCD_FEATURE_FLAG,
597 MODEL_PCD_DYNAMIC_EX,
598 MODEL_PCD_DYNAMIC,
599 MODEL_EFI_GUID,
600 MODEL_EFI_PROTOCOL,
601 MODEL_EFI_PPI,
602 MODEL_META_DATA_USER_EXTENSION]:
603 EdkLogger.error('Parser', FORMAT_INVALID,
604 "Section [%s] is not allowed in inf file without version" % (self._SectionName),
605 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
606 elif self._SectionType in [MODEL_EFI_INCLUDE,
607 MODEL_EFI_LIBRARY_INSTANCE,
608 MODEL_META_DATA_NMAKE]:
609 EdkLogger.error('Parser', FORMAT_INVALID,
610 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
611 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
612 continue
613 # merge two lines specified by '\' in section NMAKE
614 elif self._SectionType == MODEL_META_DATA_NMAKE:
615 if Line[-1] == '\\':
616 if NextLine == '':
617 self._CurrentLine = NmakeLine + Line[0:-1]
618 NmakeLine = ''
619 else:
620 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
621 self._CurrentLine = NmakeLine + Line[0:-1]
622 NmakeLine = ''
623 else:
624 NmakeLine = NmakeLine + ' ' + Line[0:-1]
625 continue
626 else:
627 self._CurrentLine = NmakeLine + Line
628 NmakeLine = ''
629
630 # section content
631 self._ValueList = ['', '', '']
632 # parse current line, result will be put in self._ValueList
633 self._SectionParser[self._SectionType](self)
634 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
635 self._ItemType = -1
636 Comments = []
637 continue
638 if Comment:
639 Comments.append((Comment, Index + 1))
640 if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:
641 CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)
642 #
643 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
644 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
645 #
646 for Arch, Platform, _ in self._Scope:
647 LastItem = self._Store(self._SectionType,
648 self._ValueList[0],
649 self._ValueList[1],
650 self._ValueList[2],
651 Arch,
652 Platform,
653 self._Owner[-1],
654 self._LineIndex + 1,
655 - 1,
656 self._LineIndex + 1,
657 - 1,
658 0
659 )
660 for Comment, LineNo in Comments:
661 self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,
662 LastItem, LineNo, -1, LineNo, -1, 0)
663 Comments = []
664 SectionComments = []
665 TailComments.extend(SectionComments + Comments)
666 if IsFindBlockComment:
667 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
668 File=self.MetaFile)
669
670 # If there are tail comments in INF file, save to database whatever the comments are
671 for Comment in TailComments:
672 self._Store(MODEL_META_DATA_TAIL_COMMENT, Comment[0], '', '', TAB_COMMON,
673 TAB_COMMON, self._Owner[-1], -1, -1, -1, -1, 0)
674 self._Done()
675
676 ## Data parser for the format in which there's path
677 #
678 # Only path can have macro used. So we need to replace them before use.
679 #
680 def _IncludeParser(self):
681 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
682 self._ValueList[0:len(TokenList)] = TokenList
683 Macros = self._Macros
684 if Macros:
685 for Index in range(0, len(self._ValueList)):
686 Value = self._ValueList[Index]
687 if not Value:
688 continue
689
690 if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
691 Value = '$(EDK_SOURCE)' + Value[17:]
692 if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:
693 pass
694 elif Value.startswith('.'):
695 pass
696 elif Value.startswith('$('):
697 pass
698 else:
699 Value = '$(EFI_SOURCE)/' + Value
700
701 self._ValueList[Index] = ReplaceMacro(Value, Macros)
702
703 ## Parse [Sources] section
704 #
705 # Only path can have macro used. So we need to replace them before use.
706 #
707 @ParseMacro
708 def _SourceFileParser(self):
709 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
710 self._ValueList[0:len(TokenList)] = TokenList
711 Macros = self._Macros
712 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
713 if 'COMPONENT_TYPE' in Macros:
714 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
715 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
716 if self._Defines['BASE_NAME'] == 'Microcode':
717 pass
718 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
719
720 ## Parse [Binaries] section
721 #
722 # Only path can have macro used. So we need to replace them before use.
723 #
724 @ParseMacro
725 def _BinaryFileParser(self):
726 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
727 if len(TokenList) < 2:
728 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
729 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
730 File=self.MetaFile, Line=self._LineIndex + 1)
731 if not TokenList[0]:
732 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
733 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
734 File=self.MetaFile, Line=self._LineIndex + 1)
735 if not TokenList[1]:
736 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
737 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
738 File=self.MetaFile, Line=self._LineIndex + 1)
739 self._ValueList[0:len(TokenList)] = TokenList
740 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
741
742 ## [nmake] section parser (Edk.x style only)
743 def _NmakeParser(self):
744 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
745 self._ValueList[0:len(TokenList)] = TokenList
746 # remove macros
747 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
748 # remove self-reference in macro setting
749 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
750
751 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
752 @ParseMacro
753 def _PcdParser(self):
754 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
755 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
756 if len(ValueList) != 2:
757 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
758 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
759 File=self.MetaFile, Line=self._LineIndex + 1)
760 self._ValueList[0:1] = ValueList
761 if len(TokenList) > 1:
762 self._ValueList[2] = TokenList[1]
763 if self._ValueList[0] == '' or self._ValueList[1] == '':
764 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
765 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
766 File=self.MetaFile, Line=self._LineIndex + 1)
767
768 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
769 if self._ValueList[2] != '':
770 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
771 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
772 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
773 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
774 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
775 if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:
776 self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType
777 elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:
778 EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",
779 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
780 File=self.MetaFile, Line=self._LineIndex + 1)
781
782 ## [depex] section parser
783 @ParseMacro
784 def _DepexParser(self):
785 self._ValueList[0:1] = [self._CurrentLine]
786
787 _SectionParser = {
788 MODEL_UNKNOWN : MetaFileParser._Skip,
789 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
790 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
791 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules
792 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules
793 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
794 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
795 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules
796 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
797 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
798 MODEL_PCD_FEATURE_FLAG : _PcdParser,
799 MODEL_PCD_DYNAMIC_EX : _PcdParser,
800 MODEL_PCD_DYNAMIC : _PcdParser,
801 MODEL_EFI_SOURCE_FILE : _SourceFileParser,
802 MODEL_EFI_GUID : MetaFileParser._CommonParser,
803 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
804 MODEL_EFI_PPI : MetaFileParser._CommonParser,
805 MODEL_EFI_DEPEX : _DepexParser,
806 MODEL_EFI_BINARY_FILE : _BinaryFileParser,
807 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
808 }
809
810 ## DSC file parser class
811 #
812 # @param FilePath The path of platform description file
813 # @param FileType The raw data of DSC file
814 # @param Table Database used to retrieve module/package information
815 # @param Macros Macros used for replacement in file
816 # @param Owner Owner ID (for sub-section parsing)
817 # @param From ID from which the data comes (for !INCLUDE directive)
818 #
819 class DscParser(MetaFileParser):
820 # DSC file supported data types (one type per section)
821 DataType = {
822 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
823 TAB_DEFAULT_STORES.upper() : MODEL_EFI_DEFAULT_STORES,
824 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
825 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
826 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
827 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
828 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
829 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
830 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
831 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
832 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
833 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
834 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
835 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
836 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
837 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
838 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,
839 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
840 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,
841 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,
842 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
843 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
844 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
845 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
846 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
847 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
848 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
849 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,
850 }
851
852 # Valid names in define section
853 DefineKeywords = [
854 "DSC_SPECIFICATION",
855 "PLATFORM_NAME",
856 "PLATFORM_GUID",
857 "PLATFORM_VERSION",
858 "SKUID_IDENTIFIER",
859 "PCD_INFO_GENERATION",
860 "PCD_VAR_CHECK_GENERATION",
861 "SUPPORTED_ARCHITECTURES",
862 "BUILD_TARGETS",
863 "OUTPUT_DIRECTORY",
864 "FLASH_DEFINITION",
865 "BUILD_NUMBER",
866 "RFC_LANGUAGES",
867 "ISO_LANGUAGES",
868 "TIME_STAMP_FILE",
869 "VPD_TOOL_GUID",
870 "FIX_LOAD_TOP_MEMORY_ADDRESS",
871 "PREBUILD",
872 "POSTBUILD"
873 ]
874
875 SubSectionDefineKeywords = [
876 "FILE_GUID"
877 ]
878
879 SymbolPattern = ValueExpression.SymbolPattern
880
881 IncludedFiles = set()
882
883 ## Constructor of DscParser
884 #
885 # Initialize object of DscParser
886 #
887 # @param FilePath The path of platform description file
888 # @param FileType The raw data of DSC file
889 # @param Arch Default Arch value for filtering sections
890 # @param Table Database used to retrieve module/package information
891 # @param Owner Owner ID (for sub-section parsing)
892 # @param From ID from which the data comes (for !INCLUDE directive)
893 #
894 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
895 # prevent re-initialization
896 if hasattr(self, "_Table") and self._Table is Table:
897 return
898 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)
899 self._Version = 0x00010005 # Only EDK2 dsc file is supported
900 # to store conditional directive evaluation result
901 self._DirectiveStack = []
902 self._DirectiveEvalStack = []
903 self._Enabled = 1
904
905 #
906 # Specify whether current line is in uncertain condition
907 #
908 self._InDirective = -1
909
910 # Final valid replacable symbols
911 self._Symbols = {}
912 #
913 # Map the ID between the original table and new table to track
914 # the owner item
915 #
916 self._IdMapping = {-1:-1}
917
918 self._PcdCodeValue = ""
919 self._PcdDataTypeCODE = False
920 self._CurrentPcdName = ""
921 self._Content = None
922
923 ## Parser starter
924 def Start(self):
925 Content = ''
926 try:
927 Content = open(str(self.MetaFile), 'r').readlines()
928 except:
929 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
930
931 OwnerId = {}
932
933 Content = self.ProcessMultipleLineCODEValue(Content)
934
935 for Index in range(0, len(Content)):
936 Line = CleanString(Content[Index])
937 # skip empty line
938 if Line == '':
939 continue
940
941 self._CurrentLine = Line
942 self._LineIndex = Index
943 if self._InSubsection and self._Owner[-1] == -1:
944 self._Owner.append(self._LastItem)
945
946 # section header
947 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
948 self._SectionType = MODEL_META_DATA_SECTION_HEADER
949 # subsection ending
950 elif Line[0] == '}' and self._InSubsection:
951 self._InSubsection = False
952 self._SubsectionType = MODEL_UNKNOWN
953 self._SubsectionName = ''
954 self._Owner[-1] = -1
955 OwnerId.clear()
956 continue
957 # subsection header
958 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
959 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
960 # directive line
961 elif Line[0] == '!':
962 TokenList = GetSplitValueList(Line, ' ', 1)
963 if TokenList[0] == TAB_INCLUDE:
964 for Arch, ModuleType, DefaultStore in self._Scope:
965 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
966 self._Owner[-1] = OwnerId[Arch]
967 self._DirectiveParser()
968 else:
969 self._DirectiveParser()
970 continue
971 if Line[0] == TAB_OPTION_START and not self._InSubsection:
972 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)
973
974 if self._InSubsection:
975 SectionType = self._SubsectionType
976 else:
977 SectionType = self._SectionType
978 self._ItemType = SectionType
979
980 self._ValueList = ['', '', '']
981 # "SET pcd = pcd_expression" syntax is not supported in Dsc file.
982 if self._CurrentLine.upper().strip().startswith("SET "):
983 EdkLogger.error('Parser', FORMAT_INVALID, '''"SET pcd = pcd_expression" syntax is not support in Dsc file''',
984 ExtraData=self._CurrentLine,
985 File=self.MetaFile, Line=self._LineIndex + 1)
986 self._SectionParser[SectionType](self)
987 if self._ValueList is None:
988 continue
989 #
990 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
991 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
992 #
993 for Arch, ModuleType, DefaultStore in self._Scope:
994 Owner = self._Owner[-1]
995 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
996 Owner = OwnerId[Arch]
997 self._LastItem = self._Store(
998 self._ItemType,
999 self._ValueList[0],
1000 self._ValueList[1],
1001 self._ValueList[2],
1002 Arch,
1003 ModuleType,
1004 DefaultStore,
1005 Owner,
1006 self._From,
1007 self._LineIndex + 1,
1008 - 1,
1009 self._LineIndex + 1,
1010 - 1,
1011 self._Enabled
1012 )
1013 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
1014 OwnerId[Arch] = self._LastItem
1015
1016 if self._DirectiveStack:
1017 Type, Line, Text = self._DirectiveStack[-1]
1018 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
1019 ExtraData=Text, File=self.MetaFile, Line=Line)
1020 self._Done()
1021
1022 ## <subsection_header> parser
1023 def _SubsectionHeaderParser(self):
1024 self._SubsectionName = self._CurrentLine[1:-1].upper()
1025 if self._SubsectionName in self.DataType:
1026 self._SubsectionType = self.DataType[self._SubsectionName]
1027 else:
1028 self._SubsectionType = MODEL_UNKNOWN
1029 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
1030 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1031 self._ValueList[0] = self._SubsectionName
1032
1033 ## Directive statement parser
1034 def _DirectiveParser(self):
1035 self._ValueList = ['', '', '']
1036 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
1037 self._ValueList[0:len(TokenList)] = TokenList
1038
1039 # Syntax check
1040 DirectiveName = self._ValueList[0].upper()
1041 if DirectiveName not in self.DataType:
1042 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
1043 File=self.MetaFile, Line=self._LineIndex + 1)
1044
1045 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
1046 self._InDirective += 1
1047
1048 if DirectiveName in ['!ENDIF']:
1049 self._InDirective -= 1
1050
1051 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
1052 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
1053 File=self.MetaFile, Line=self._LineIndex + 1,
1054 ExtraData=self._CurrentLine)
1055
1056 ItemType = self.DataType[DirectiveName]
1057 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]
1058 if ItemType == MODEL_META_DATA_INCLUDE:
1059 Scope = self._Scope
1060 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:
1061 Scope = self._Scope
1062 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1063 # Remove all directives between !if and !endif, including themselves
1064 while self._DirectiveStack:
1065 # Remove any !else or !elseif
1066 DirectiveInfo = self._DirectiveStack.pop()
1067 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1068 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1069 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1070 break
1071 else:
1072 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
1073 File=self.MetaFile, Line=self._LineIndex + 1,
1074 ExtraData=self._CurrentLine)
1075 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:
1076 # Break if there's a !else is followed by a !elseif
1077 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
1078 self._DirectiveStack and \
1079 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1080 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
1081 File=self.MetaFile, Line=self._LineIndex + 1,
1082 ExtraData=self._CurrentLine)
1083 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
1084
1085 #
1086 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1087 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1088 #
1089 for Arch, ModuleType, DefaultStore in Scope:
1090 self._LastItem = self._Store(
1091 ItemType,
1092 self._ValueList[0],
1093 self._ValueList[1],
1094 self._ValueList[2],
1095 Arch,
1096 ModuleType,
1097 DefaultStore,
1098 self._Owner[-1],
1099 self._From,
1100 self._LineIndex + 1,
1101 - 1,
1102 self._LineIndex + 1,
1103 - 1,
1104 0
1105 )
1106
1107 ## [defines] section parser
1108 @ParseMacro
1109 def _DefineParser(self):
1110 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1111 self._ValueList[1:len(TokenList)] = TokenList
1112
1113 # Syntax check
1114 if not self._ValueList[1]:
1115 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
1116 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1117 if not self._ValueList[2]:
1118 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
1119 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1120 if (not self._ValueList[1] in self.DefineKeywords and
1121 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):
1122 EdkLogger.error('Parser', FORMAT_INVALID,
1123 "Unknown keyword found: %s. "
1124 "If this is a macro you must "
1125 "add it as a DEFINE in the DSC" % self._ValueList[1],
1126 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1127 if not self._InSubsection:
1128 self._Defines[self._ValueList[1]] = self._ValueList[2]
1129 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
1130
1131 @ParseMacro
1132 def _SkuIdParser(self):
1133 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1134 if len(TokenList) not in (2, 3):
1135 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",
1136 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1137 self._ValueList[0:len(TokenList)] = TokenList
1138 @ParseMacro
1139 def _DefaultStoresParser(self):
1140 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1141 if len(TokenList) != 2:
1142 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",
1143 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1144 self._ValueList[0:len(TokenList)] = TokenList
1145
1146 ## Parse Edk style of library modules
1147 @ParseMacro
1148 def _LibraryInstanceParser(self):
1149 self._ValueList[0] = self._CurrentLine
1150
1151 def ProcessMultipleLineCODEValue(self,Content):
1152 CODEBegin = False
1153 CODELine = ""
1154 continuelinecount = 0
1155 newContent = []
1156 for Index in range(0, len(Content)):
1157 Line = Content[Index]
1158 if CODEBegin:
1159 CODELine = CODELine + Line
1160 continuelinecount +=1
1161 if ")}" in Line:
1162 newContent.append(CODELine)
1163 for _ in range(continuelinecount):
1164 newContent.append("")
1165 CODEBegin = False
1166 CODELine = ""
1167 continuelinecount = 0
1168 else:
1169 if not Line:
1170 newContent.append(Line)
1171 continue
1172 if "{CODE(" not in Line:
1173 newContent.append(Line)
1174 continue
1175 elif CODEPattern.findall(Line):
1176 newContent.append(Line)
1177 continue
1178 else:
1179 CODEBegin = True
1180 CODELine = Line
1181
1182 return newContent
1183
1184 def _DecodeCODEData(self):
1185 pass
1186 ## PCD sections parser
1187 #
1188 # [PcdsFixedAtBuild]
1189 # [PcdsPatchableInModule]
1190 # [PcdsFeatureFlag]
1191 # [PcdsDynamicEx
1192 # [PcdsDynamicExDefault]
1193 # [PcdsDynamicExVpd]
1194 # [PcdsDynamicExHii]
1195 # [PcdsDynamic]
1196 # [PcdsDynamicDefault]
1197 # [PcdsDynamicVpd]
1198 # [PcdsDynamicHii]
1199 #
1200 @ParseMacro
1201 def _PcdParser(self):
1202 if self._PcdDataTypeCODE:
1203 self._PcdCodeValue = self._PcdCodeValue + "\n " + self._CurrentLine
1204 if self._CurrentLine.endswith(")}"):
1205 self._CurrentLine = "|".join((self._CurrentPcdName, self._PcdCodeValue))
1206 self._PcdDataTypeCODE = False
1207 self._PcdCodeValue = ""
1208 else:
1209 self._ValueList = None
1210 return
1211 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1212 self._CurrentPcdName = TokenList[0]
1213 if len(TokenList) == 2 and TokenList[1].strip().startswith("{CODE"):
1214 self._PcdDataTypeCODE = True
1215 self._PcdCodeValue = TokenList[1].strip()
1216
1217 if self._PcdDataTypeCODE:
1218 if self._CurrentLine.endswith(")}"):
1219 self._PcdDataTypeCODE = False
1220 self._PcdCodeValue = ""
1221 else:
1222 self._ValueList = None
1223 return
1224 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1225 PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)
1226 if len(PcdNameTockens) == 2:
1227 self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]
1228 elif len(PcdNameTockens) == 3:
1229 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]
1230 elif len(PcdNameTockens) > 3:
1231 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])
1232 if len(TokenList) == 2:
1233 self._ValueList[2] = TokenList[1]
1234 if self._ValueList[0] == '' or self._ValueList[1] == '':
1235 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1236 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1237 File=self.MetaFile, Line=self._LineIndex + 1)
1238 if self._ValueList[2] == '':
1239 #
1240 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default
1241 #
1242 if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
1243 return
1244 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
1245 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1246 File=self.MetaFile, Line=self._LineIndex + 1)
1247
1248 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1249 ValueList = GetSplitValueList(self._ValueList[2])
1250 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \
1251 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
1252 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
1253 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1254
1255 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string
1256 if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:
1257 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1258 if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:
1259 EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",
1260 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1261
1262 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1263 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1264 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
1265 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
1266 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
1267 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
1268
1269
1270 ## [components] section parser
1271 @ParseMacro
1272 def _ComponentParser(self):
1273 if self._CurrentLine[-1] == '{':
1274 self._ValueList[0] = self._CurrentLine[0:-1].strip()
1275 self._InSubsection = True
1276 self._SubsectionType = MODEL_UNKNOWN
1277 else:
1278 self._ValueList[0] = self._CurrentLine
1279
1280 ## [LibraryClasses] section
1281 @ParseMacro
1282 def _LibraryClassParser(self):
1283 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1284 if len(TokenList) < 2:
1285 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
1286 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1287 File=self.MetaFile, Line=self._LineIndex + 1)
1288 if TokenList[0] == '':
1289 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
1290 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1291 File=self.MetaFile, Line=self._LineIndex + 1)
1292 if TokenList[1] == '':
1293 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
1294 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1295 File=self.MetaFile, Line=self._LineIndex + 1)
1296
1297 self._ValueList[0:len(TokenList)] = TokenList
1298
1299 def _CompponentSourceOverridePathParser(self):
1300 self._ValueList[0] = self._CurrentLine
1301
1302 ## [BuildOptions] section parser
1303 @ParseMacro
1304 def _BuildOptionParser(self):
1305 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
1306 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1307 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
1308 if len(TokenList2) == 2:
1309 self._ValueList[0] = TokenList2[0] # toolchain family
1310 self._ValueList[1] = TokenList2[1] # keys
1311 else:
1312 self._ValueList[1] = TokenList[0]
1313 if len(TokenList) == 2: # value
1314 self._ValueList[2] = TokenList[1]
1315
1316 if self._ValueList[1].count('_') != 4:
1317 EdkLogger.error(
1318 'Parser',
1319 FORMAT_INVALID,
1320 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
1321 ExtraData=self._CurrentLine,
1322 File=self.MetaFile,
1323 Line=self._LineIndex + 1
1324 )
1325
1326 ## Override parent's method since we'll do all macro replacements in parser
1327 @property
1328 def _Macros(self):
1329 Macros = {}
1330 Macros.update(self._FileLocalMacros)
1331 Macros.update(self._GetApplicableSectionMacro())
1332 Macros.update(GlobalData.gEdkGlobal)
1333 Macros.update(GlobalData.gPlatformDefines)
1334 Macros.update(GlobalData.gCommandLineDefines)
1335 # PCD cannot be referenced in macro definition
1336 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
1337 Macros.update(self._Symbols)
1338 if GlobalData.BuildOptionPcd:
1339 for Item in GlobalData.BuildOptionPcd:
1340 if isinstance(Item, tuple):
1341 continue
1342 PcdName, TmpValue = Item.split("=")
1343 TmpValue = BuildOptionValue(TmpValue, self._GuidDict)
1344 Macros[PcdName.strip()] = TmpValue
1345 return Macros
1346
1347 def _PostProcess(self):
1348 Processer = {
1349 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,
1350 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,
1351 MODEL_META_DATA_HEADER : self.__ProcessDefine,
1352 MODEL_META_DATA_DEFINE : self.__ProcessDefine,
1353 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,
1354 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,
1355 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,
1356 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,
1357 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,
1358 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,
1359 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,
1360 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,
1361 MODEL_EFI_SKU_ID : self.__ProcessSkuId,
1362 MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,
1363 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,
1364 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,
1365 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,
1366 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,
1367 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,
1368 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,
1369 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,
1370 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,
1371 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,
1372 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,
1373 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,
1374 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,
1375 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,
1376 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,
1377 MODEL_UNKNOWN : self._Skip,
1378 MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,
1379 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,
1380 }
1381
1382 self._Table = MetaFileStorage(self._RawTable.DB, self.MetaFile, MODEL_FILE_DSC, True)
1383 self._DirectiveStack = []
1384 self._DirectiveEvalStack = []
1385 self._FileWithError = self.MetaFile
1386 self._FileLocalMacros = {}
1387 self._SectionsMacroDict.clear()
1388 GlobalData.gPlatformDefines = {}
1389
1390 # Get all macro and PCD which has straitforward value
1391 self.__RetrievePcdValue()
1392 self._Content = self._RawTable.GetAll()
1393 self._ContentIndex = 0
1394 self._InSubsection = False
1395 while self._ContentIndex < len(self._Content) :
1396 Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \
1397 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
1398
1399 if self._From < 0:
1400 self._FileWithError = self.MetaFile
1401
1402 self._ContentIndex += 1
1403
1404 self._Scope = [[S1, S2, S3]]
1405 #
1406 # For !include directive, handle it specially,
1407 # merge arch and module type in case of duplicate items
1408 #
1409 while self._ItemType == MODEL_META_DATA_INCLUDE:
1410 if self._ContentIndex >= len(self._Content):
1411 break
1412 Record = self._Content[self._ContentIndex]
1413 if LineStart == Record[10] and LineEnd == Record[12]:
1414 if [Record[5], Record[6], Record[7]] not in self._Scope:
1415 self._Scope.append([Record[5], Record[6], Record[7]])
1416 self._ContentIndex += 1
1417 else:
1418 break
1419
1420 self._LineIndex = LineStart - 1
1421 self._ValueList = [V1, V2, V3]
1422
1423 if Owner > 0 and Owner in self._IdMapping:
1424 self._InSubsection = True
1425 else:
1426 self._InSubsection = False
1427 try:
1428 Processer[self._ItemType]()
1429 except EvaluationException as Excpt:
1430 #
1431 # Only catch expression evaluation error here. We need to report
1432 # the precise number of line on which the error occurred
1433 #
1434 if hasattr(Excpt, 'Pcd'):
1435 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
1436 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
1437 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
1438 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1439 " of the DSC file, and it is currently defined in this section:"
1440 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
1441 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1442 Line=self._LineIndex + 1)
1443 else:
1444 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
1445 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1446 Line=self._LineIndex + 1)
1447 else:
1448 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1449 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1450 Line=self._LineIndex + 1)
1451 except MacroException as Excpt:
1452 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
1453 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1454 Line=self._LineIndex + 1)
1455
1456 if self._ValueList is None:
1457 continue
1458
1459 NewOwner = self._IdMapping.get(Owner, -1)
1460 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
1461 self._LastItem = self._Store(
1462 self._ItemType,
1463 self._ValueList[0],
1464 self._ValueList[1],
1465 self._ValueList[2],
1466 S1,
1467 S2,
1468 S3,
1469 NewOwner,
1470 self._From,
1471 self._LineIndex + 1,
1472 - 1,
1473 self._LineIndex + 1,
1474 - 1,
1475 self._Enabled
1476 )
1477 self._IdMapping[Id] = self._LastItem
1478
1479 GlobalData.gPlatformDefines.update(self._FileLocalMacros)
1480 self._PostProcessed = True
1481 self._Content = None
1482 def _ProcessError(self):
1483 if not self._Enabled:
1484 return
1485 EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)
1486
1487 def __ProcessSectionHeader(self):
1488 self._SectionName = self._ValueList[0]
1489 if self._SectionName in self.DataType:
1490 self._SectionType = self.DataType[self._SectionName]
1491 else:
1492 self._SectionType = MODEL_UNKNOWN
1493
1494 def __ProcessSubsectionHeader(self):
1495 self._SubsectionName = self._ValueList[0]
1496 if self._SubsectionName in self.DataType:
1497 self._SubsectionType = self.DataType[self._SubsectionName]
1498 else:
1499 self._SubsectionType = MODEL_UNKNOWN
1500
1501 def __RetrievePcdValue(self):
1502 Content = open(str(self.MetaFile), 'r').readlines()
1503 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
1504 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
1505 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
1506 MODEL_PCD_DYNAMIC_EX_VPD):
1507 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
1508 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:
1509 Name = TokenSpaceGuid + '.' + PcdName
1510 if Name not in GlobalData.gPlatformOtherPcds:
1511 PcdLine = Line
1512 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
1513 Line -= 1
1514 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
1515
1516 def __ProcessDefine(self):
1517 if not self._Enabled:
1518 return
1519
1520 Type, Name, Value = self._ValueList
1521 Value = ReplaceMacro(Value, self._Macros, False)
1522 #
1523 # If it is <Defines>, return
1524 #
1525 if self._InSubsection:
1526 self._ValueList = [Type, Name, Value]
1527 return
1528
1529 if self._ItemType == MODEL_META_DATA_DEFINE:
1530 if self._SectionType == MODEL_META_DATA_HEADER:
1531 self._FileLocalMacros[Name] = Value
1532 else:
1533 self._ConstructSectionMacroDict(Name, Value)
1534 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
1535 GlobalData.gEdkGlobal[Name] = Value
1536
1537 #
1538 # Keyword in [Defines] section can be used as Macros
1539 #
1540 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
1541 self._FileLocalMacros[Name] = Value
1542
1543 self._ValueList = [Type, Name, Value]
1544
1545 def __ProcessDirective(self):
1546 Result = None
1547 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1548 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
1549 Macros = self._Macros
1550 Macros.update(GlobalData.gGlobalDefines)
1551 try:
1552 Result = ValueExpression(self._ValueList[1], Macros)()
1553 except SymbolNotFound as Exc:
1554 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1555 Result = False
1556 except WrnExpression as Excpt:
1557 #
1558 # Catch expression evaluation warning here. We need to report
1559 # the precise number of line and return the evaluation result
1560 #
1561 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
1562 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1563 Line=self._LineIndex + 1)
1564 Result = Excpt.result
1565
1566 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1567 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1568 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1569 self._DirectiveStack.append(self._ItemType)
1570 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
1571 Result = bool(Result)
1572 else:
1573 Macro = self._ValueList[1]
1574 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
1575 Result = Macro in self._Macros
1576 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
1577 Result = not Result
1578 self._DirectiveEvalStack.append(Result)
1579 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
1580 self._DirectiveStack.append(self._ItemType)
1581 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1582 self._DirectiveEvalStack.append(bool(Result))
1583 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1584 self._DirectiveStack.append(self._ItemType)
1585 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1586 self._DirectiveEvalStack.append(True)
1587 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1588 # Back to the nearest !if/!ifdef/!ifndef
1589 while self._DirectiveStack:
1590 self._DirectiveEvalStack.pop()
1591 Directive = self._DirectiveStack.pop()
1592 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1593 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1594 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1595 break
1596 elif self._ItemType == MODEL_META_DATA_INCLUDE:
1597 # The included file must be relative to workspace or same directory as DSC file
1598 __IncludeMacros = {}
1599 #
1600 # Allow using system environment variables in path after !include
1601 #
1602 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
1603 if "ECP_SOURCE" in GlobalData.gGlobalDefines:
1604 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']
1605 #
1606 # During GenFds phase call DSC parser, will go into this branch.
1607 #
1608 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines:
1609 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']
1610
1611 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']
1612 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']
1613 #
1614 # Allow using MACROs comes from [Defines] section to keep compatible.
1615 #
1616 __IncludeMacros.update(self._Macros)
1617
1618 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
1619 #
1620 # First search the include file under the same directory as DSC file
1621 #
1622 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
1623 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
1624 if ErrorCode != 0:
1625 #
1626 # Also search file under the WORKSPACE directory
1627 #
1628 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
1629 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
1630 if ErrorCode != 0:
1631 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
1632 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
1633
1634 self._FileWithError = IncludedFile1
1635
1636 FromItem = self._Content[self._ContentIndex - 1][0]
1637 if self._InSubsection:
1638 Owner = self._Content[self._ContentIndex - 1][8]
1639 else:
1640 Owner = self._Content[self._ContentIndex - 1][0]
1641 IncludedFileTable = MetaFileStorage(self._RawTable.DB, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)
1642 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,
1643 Owner=Owner, From=FromItem)
1644
1645 self.IncludedFiles.add (IncludedFile1)
1646
1647 # set the parser status with current status
1648 Parser._SectionName = self._SectionName
1649 Parser._SubsectionType = self._SubsectionType
1650 Parser._InSubsection = self._InSubsection
1651 Parser._SectionType = self._SectionType
1652 Parser._Scope = self._Scope
1653 Parser._Enabled = self._Enabled
1654 # Parse the included file
1655 Parser.StartParse()
1656 # Insert all records in the table for the included file into dsc file table
1657 Records = IncludedFileTable.GetAll()
1658 if Records:
1659 self._Content[self._ContentIndex:self._ContentIndex] = Records
1660 self._Content.pop(self._ContentIndex - 1)
1661 self._ValueList = None
1662 self._ContentIndex -= 1
1663
1664 def __ProcessSkuId(self):
1665 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1666 for Value in self._ValueList]
1667 def __ProcessDefaultStores(self):
1668 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1669 for Value in self._ValueList]
1670
1671 def __ProcessLibraryInstance(self):
1672 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
1673
1674 def __ProcessLibraryClass(self):
1675 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
1676
1677 def __ProcessPcd(self):
1678 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
1679 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
1680 return
1681
1682 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
1683 if not Valid:
1684 if self._ItemType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
1685 if ValList[1] != TAB_VOID and StructPattern.match(ValList[1]) is None and ValList[2]:
1686 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect. The datum type info should be VOID* or a valid struct name.", File=self._FileWithError,
1687 Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1688 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,
1689 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1690 PcdValue = ValList[Index]
1691 if PcdValue and "." not in self._ValueList[0]:
1692 try:
1693 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
1694 except WrnExpression as Value:
1695 ValList[Index] = Value.result
1696 except:
1697 pass
1698
1699 if ValList[Index] == 'True':
1700 ValList[Index] = '1'
1701 if ValList[Index] == 'False':
1702 ValList[Index] = '0'
1703
1704 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):
1705 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1706 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1707 try:
1708 self._ValueList[2] = '|'.join(ValList)
1709 except Exception:
1710 print(ValList)
1711
1712 def __ProcessComponent(self):
1713 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1714
1715 def __ProcessSourceOverridePath(self):
1716 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1717
1718 def __ProcessBuildOption(self):
1719 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
1720 for Value in self._ValueList]
1721
1722 _SectionParser = {
1723 MODEL_META_DATA_HEADER : _DefineParser,
1724 MODEL_EFI_SKU_ID : _SkuIdParser,
1725 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,
1726 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
1727 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
1728 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1729 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1730 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1731 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
1732 MODEL_PCD_DYNAMIC_HII : _PcdParser,
1733 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
1734 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
1735 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
1736 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
1737 MODEL_META_DATA_COMPONENT : _ComponentParser,
1738 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,
1739 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1740 MODEL_UNKNOWN : MetaFileParser._Skip,
1741 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
1742 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1743 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1744 }
1745
1746 ## DEC file parser class
1747 #
1748 # @param FilePath The path of platform description file
1749 # @param FileType The raw data of DSC file
1750 # @param Table Database used to retrieve module/package information
1751 # @param Macros Macros used for replacement in file
1752 #
1753 class DecParser(MetaFileParser):
1754 # DEC file supported data types (one type per section)
1755 DataType = {
1756 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1757 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1758 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1759 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1760 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1761 TAB_PPIS.upper() : MODEL_EFI_PPI,
1762 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1763 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1764 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1765 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1766 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1767 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1768 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
1769 }
1770
1771 ## Constructor of DecParser
1772 #
1773 # Initialize object of DecParser
1774 #
1775 # @param FilePath The path of platform description file
1776 # @param FileType The raw data of DSC file
1777 # @param Arch Default Arch value for filtering sections
1778 # @param Table Database used to retrieve module/package information
1779 #
1780 def __init__(self, FilePath, FileType, Arch, Table):
1781 # prevent re-initialization
1782 if hasattr(self, "_Table"):
1783 return
1784 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)
1785 self._Comments = []
1786 self._Version = 0x00010005 # Only EDK2 dec file is supported
1787 self._AllPCDs = [] # Only for check duplicate PCD
1788 self._AllPcdDict = {}
1789
1790 self._CurrentStructurePcdName = ""
1791 self._include_flag = False
1792 self._package_flag = False
1793
1794 ## Parser starter
1795 def Start(self):
1796 Content = ''
1797 try:
1798 Content = open(str(self.MetaFile), 'r').readlines()
1799 except:
1800 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1801
1802 self._DefinesCount = 0
1803 for Index in range(0, len(Content)):
1804 Line, Comment = CleanString2(Content[Index])
1805 self._CurrentLine = Line
1806 self._LineIndex = Index
1807
1808 # save comment for later use
1809 if Comment:
1810 self._Comments.append((Comment, self._LineIndex + 1))
1811 # skip empty line
1812 if Line == '':
1813 continue
1814
1815 # section header
1816 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
1817 self._SectionHeaderParser()
1818 if self._SectionName == TAB_DEC_DEFINES.upper():
1819 self._DefinesCount += 1
1820 self._Comments = []
1821 continue
1822 if self._SectionType == MODEL_UNKNOWN:
1823 EdkLogger.error("Parser", FORMAT_INVALID,
1824 ""
1825 "Not able to determine \"%s\" in which section."%self._CurrentLine,
1826 self.MetaFile, self._LineIndex + 1)
1827 elif len(self._SectionType) == 0:
1828 self._Comments = []
1829 continue
1830
1831 # section content
1832 self._ValueList = ['', '', '']
1833 self._SectionParser[self._SectionType[0]](self)
1834 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
1835 self._ItemType = -1
1836 self._Comments = []
1837 continue
1838
1839 #
1840 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1841 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1842 #
1843 for Arch, ModuleType, Type in self._Scope:
1844 self._LastItem = self._Store(
1845 Type,
1846 self._ValueList[0],
1847 self._ValueList[1],
1848 self._ValueList[2],
1849 Arch,
1850 ModuleType,
1851 self._Owner[-1],
1852 self._LineIndex + 1,
1853 - 1,
1854 self._LineIndex + 1,
1855 - 1,
1856 0
1857 )
1858 for Comment, LineNo in self._Comments:
1859 self._Store(
1860 MODEL_META_DATA_COMMENT,
1861 Comment,
1862 self._ValueList[0],
1863 self._ValueList[1],
1864 Arch,
1865 ModuleType,
1866 self._LastItem,
1867 LineNo,
1868 - 1,
1869 LineNo,
1870 - 1,
1871 0
1872 )
1873 self._Comments = []
1874 if self._DefinesCount > 1:
1875 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )
1876 if self._DefinesCount == 0:
1877 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)
1878 self._Done()
1879
1880
1881 ## Section header parser
1882 #
1883 # The section header is always in following format:
1884 #
1885 # [section_name.arch<.platform|module_type>]
1886 #
1887 def _SectionHeaderParser(self):
1888 self._Scope = []
1889 self._SectionName = ''
1890 self._SectionType = []
1891 ArchList = set()
1892 PrivateList = set()
1893 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)
1894 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
1895 if Item == '':
1896 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
1897 "section name can NOT be empty or incorrectly use separator comma",
1898 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1899 ItemList = Item.split(TAB_SPLIT)
1900
1901 # different types of PCD are permissible in one section
1902 self._SectionName = ItemList[0].upper()
1903 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):
1904 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",
1905 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1906 if self._SectionName in self.DataType:
1907 if self.DataType[self._SectionName] not in self._SectionType:
1908 self._SectionType.append(self.DataType[self._SectionName])
1909 else:
1910 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
1911 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1912
1913 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1914 EdkLogger.error(
1915 'Parser',
1916 FORMAT_INVALID,
1917 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1918 File=self.MetaFile,
1919 Line=self._LineIndex + 1,
1920 ExtraData=self._CurrentLine
1921 )
1922 # S1 is always Arch
1923 if len(ItemList) > 1:
1924 S1 = ItemList[1].upper()
1925 else:
1926 S1 = TAB_ARCH_COMMON
1927 ArchList.add(S1)
1928 # S2 may be Platform or ModuleType
1929 if len(ItemList) > 2:
1930 S2 = ItemList[2].upper()
1931 # only Includes, GUIDs, PPIs, Protocols section have Private tag
1932 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:
1933 if S2 != 'PRIVATE':
1934 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',
1935 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1936 else:
1937 S2 = TAB_COMMON
1938 PrivateList.add(S2)
1939 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1940 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1941
1942 # 'COMMON' must not be used with specific ARCHs at the same section
1943 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:
1944 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1945 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1946
1947 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
1948 if TAB_COMMON in PrivateList and len(PrivateList) > 1:
1949 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
1950 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1951
1952 ## [guids], [ppis] and [protocols] section parser
1953 @ParseMacro
1954 def _GuidParser(self):
1955 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1956 if len(TokenList) < 2:
1957 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1958 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1959 File=self.MetaFile, Line=self._LineIndex + 1)
1960 if TokenList[0] == '':
1961 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1962 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1963 File=self.MetaFile, Line=self._LineIndex + 1)
1964 if TokenList[1] == '':
1965 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1966 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1967 File=self.MetaFile, Line=self._LineIndex + 1)
1968 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1969 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1970 ExtraData=self._CurrentLine + \
1971 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1972 File=self.MetaFile, Line=self._LineIndex + 1)
1973 self._ValueList[0] = TokenList[0]
1974 self._ValueList[1] = TokenList[1]
1975 if self._ValueList[0] not in self._GuidDict:
1976 self._GuidDict[self._ValueList[0]] = self._ValueList[1]
1977
1978 def ParsePcdName(self,namelist):
1979 if "[" in namelist[1]:
1980 pcdname = namelist[1][:namelist[1].index("[")]
1981 arrayindex = namelist[1][namelist[1].index("["):]
1982 namelist[1] = pcdname
1983 if len(namelist) == 2:
1984 namelist.append(arrayindex)
1985 else:
1986 namelist[2] = ".".join((arrayindex,namelist[2]))
1987 return namelist
1988
1989 ## PCD sections parser
1990 #
1991 # [PcdsFixedAtBuild]
1992 # [PcdsPatchableInModule]
1993 # [PcdsFeatureFlag]
1994 # [PcdsDynamicEx
1995 # [PcdsDynamic]
1996 #
1997 @ParseMacro
1998 def _PcdParser(self):
1999 if self._CurrentStructurePcdName:
2000 self._ValueList[0] = self._CurrentStructurePcdName
2001
2002 if "|" not in self._CurrentLine:
2003 if "<HeaderFiles>" == self._CurrentLine:
2004 self._include_flag = True
2005 self._package_flag = False
2006 self._ValueList = None
2007 return
2008 if "<Packages>" == self._CurrentLine:
2009 self._package_flag = True
2010 self._ValueList = None
2011 self._include_flag = False
2012 return
2013
2014 if self._include_flag:
2015 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine).hexdigest()
2016 self._ValueList[2] = self._CurrentLine
2017 if self._package_flag and "}" != self._CurrentLine:
2018 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine).hexdigest()
2019 self._ValueList[2] = self._CurrentLine
2020 if self._CurrentLine == "}":
2021 self._package_flag = False
2022 self._include_flag = False
2023 self._ValueList = None
2024 return
2025 else:
2026 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)
2027 PcdNames = self.ParsePcdName(PcdTockens[0].split(TAB_SPLIT))
2028 if len(PcdNames) == 2:
2029 if PcdNames[1].strip().endswith("]"):
2030 PcdName = PcdNames[1][:PcdNames[1].index('[')]
2031 Index = PcdNames[1][PcdNames[1].index('['):]
2032 self._ValueList[0] = TAB_SPLIT.join((PcdNames[0],PcdName))
2033 self._ValueList[1] = Index
2034 self._ValueList[2] = PcdTockens[1]
2035 else:
2036 self._CurrentStructurePcdName = ""
2037 else:
2038 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):
2039 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),
2040 File=self.MetaFile, Line=self._LineIndex + 1)
2041 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])
2042 self._ValueList[2] = PcdTockens[1]
2043 if not self._CurrentStructurePcdName:
2044 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
2045 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
2046 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
2047 # check PCD information
2048 if self._ValueList[0] == '' or self._ValueList[1] == '':
2049 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
2050 ExtraData=self._CurrentLine + \
2051 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2052 File=self.MetaFile, Line=self._LineIndex + 1)
2053 # check format of token space GUID CName
2054 if not ValueRe.match(self._ValueList[0]):
2055 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
2056 ExtraData=self._CurrentLine + \
2057 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2058 File=self.MetaFile, Line=self._LineIndex + 1)
2059 # check format of PCD CName
2060 if not ValueRe.match(self._ValueList[1]):
2061 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
2062 ExtraData=self._CurrentLine + \
2063 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2064 File=self.MetaFile, Line=self._LineIndex + 1)
2065 # check PCD datum information
2066 if len(TokenList) < 2 or TokenList[1] == '':
2067 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
2068 ExtraData=self._CurrentLine + \
2069 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2070 File=self.MetaFile, Line=self._LineIndex + 1)
2071
2072
2073 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
2074 PtrValue = ValueRe.findall(TokenList[1])
2075
2076 # Has VOID* type string, may contain "|" character in the string.
2077 if len(PtrValue) != 0:
2078 ptrValueList = re.sub(ValueRe, '', TokenList[1])
2079 ValueList = AnalyzePcdExpression(ptrValueList)
2080 ValueList[0] = PtrValue[0]
2081 else:
2082 ValueList = AnalyzePcdExpression(TokenList[1])
2083
2084
2085 # check if there's enough datum information given
2086 if len(ValueList) != 3:
2087 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
2088 ExtraData=self._CurrentLine + \
2089 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2090 File=self.MetaFile, Line=self._LineIndex + 1)
2091 # check default value
2092 if ValueList[0] == '':
2093 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
2094 ExtraData=self._CurrentLine + \
2095 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2096 File=self.MetaFile, Line=self._LineIndex + 1)
2097 # check datum type
2098 if ValueList[1] == '':
2099 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
2100 ExtraData=self._CurrentLine + \
2101 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2102 File=self.MetaFile, Line=self._LineIndex + 1)
2103 # check token of the PCD
2104 if ValueList[2] == '':
2105 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
2106 ExtraData=self._CurrentLine + \
2107 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2108 File=self.MetaFile, Line=self._LineIndex + 1)
2109
2110 PcdValue = ValueList[0]
2111 if PcdValue:
2112 try:
2113 self._GuidDict.update(self._AllPcdDict)
2114 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
2115 except BadExpression as Value:
2116 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
2117 # check format of default value against the datum type
2118 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
2119 if not IsValid:
2120 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
2121 File=self.MetaFile, Line=self._LineIndex + 1)
2122
2123 if Cause == "StructurePcd":
2124 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])
2125 self._ValueList[0] = self._CurrentStructurePcdName
2126 self._ValueList[1] = ValueList[1].strip()
2127
2128 if ValueList[0] in ['True', 'true', 'TRUE']:
2129 ValueList[0] = '1'
2130 elif ValueList[0] in ['False', 'false', 'FALSE']:
2131 ValueList[0] = '0'
2132
2133 # check for duplicate PCD definition
2134 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
2135 EdkLogger.error('Parser', FORMAT_INVALID,
2136 "The same PCD name and GUID have been already defined",
2137 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
2138 else:
2139 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
2140 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]
2141
2142 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
2143
2144 _SectionParser = {
2145 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
2146 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
2147 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
2148 MODEL_EFI_GUID : _GuidParser,
2149 MODEL_EFI_PPI : _GuidParser,
2150 MODEL_EFI_PROTOCOL : _GuidParser,
2151 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
2152 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
2153 MODEL_PCD_FEATURE_FLAG : _PcdParser,
2154 MODEL_PCD_DYNAMIC : _PcdParser,
2155 MODEL_PCD_DYNAMIC_EX : _PcdParser,
2156 MODEL_UNKNOWN : MetaFileParser._Skip,
2157 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
2158 }
2159
2160 ##
2161 #
2162 # This acts like the main() function for the script, unless it is 'import'ed into another
2163 # script.
2164 #
2165 if __name__ == '__main__':
2166 pass
2167