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