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