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