]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools: Various typo
[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 Content = open(str(self.MetaFile), 'r').readlines()
580 except:
581 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
582
583 # parse the file line by line
584 IsFindBlockComment = False
585 GetHeaderComment = False
586 TailComments = []
587 SectionComments = []
588 Comments = []
589
590 for Index in range(0, len(Content)):
591 # skip empty, commented, block commented lines
592 Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)
593 NextLine = ''
594 if Index + 1 < len(Content):
595 NextLine, NextComment = CleanString2(Content[Index + 1])
596 if Line == '':
597 if Comment:
598 Comments.append((Comment, Index + 1))
599 elif GetHeaderComment:
600 SectionComments.extend(Comments)
601 Comments = []
602 continue
603 if Line.find(TAB_COMMENT_EDK_START) > -1:
604 IsFindBlockComment = True
605 continue
606 if Line.find(TAB_COMMENT_EDK_END) > -1:
607 IsFindBlockComment = False
608 continue
609 if IsFindBlockComment:
610 continue
611
612 self._LineIndex = Index
613 self._CurrentLine = Line
614
615 # section header
616 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
617 if not GetHeaderComment:
618 for Cmt, LNo in Comments:
619 self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', TAB_COMMON,
620 TAB_COMMON, self._Owner[-1], LNo, -1, LNo, -1, 0)
621 GetHeaderComment = True
622 else:
623 TailComments.extend(SectionComments + Comments)
624 Comments = []
625 self._SectionHeaderParser()
626 # Check invalid sections
627 if self._Version < 0x00010005:
628 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
629 MODEL_EFI_LIBRARY_CLASS,
630 MODEL_META_DATA_PACKAGE,
631 MODEL_PCD_FIXED_AT_BUILD,
632 MODEL_PCD_PATCHABLE_IN_MODULE,
633 MODEL_PCD_FEATURE_FLAG,
634 MODEL_PCD_DYNAMIC_EX,
635 MODEL_PCD_DYNAMIC,
636 MODEL_EFI_GUID,
637 MODEL_EFI_PROTOCOL,
638 MODEL_EFI_PPI,
639 MODEL_META_DATA_USER_EXTENSION]:
640 EdkLogger.error('Parser', FORMAT_INVALID,
641 "Section [%s] is not allowed in inf file without version" % (self._SectionName),
642 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
643 elif self._SectionType in [MODEL_EFI_INCLUDE,
644 MODEL_EFI_LIBRARY_INSTANCE,
645 MODEL_META_DATA_NMAKE]:
646 EdkLogger.error('Parser', FORMAT_INVALID,
647 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
648 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
649 continue
650 # merge two lines specified by '\' in section NMAKE
651 elif self._SectionType == MODEL_META_DATA_NMAKE:
652 if Line[-1] == '\\':
653 if NextLine == '':
654 self._CurrentLine = NmakeLine + Line[0:-1]
655 NmakeLine = ''
656 else:
657 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
658 self._CurrentLine = NmakeLine + Line[0:-1]
659 NmakeLine = ''
660 else:
661 NmakeLine = NmakeLine + ' ' + Line[0:-1]
662 continue
663 else:
664 self._CurrentLine = NmakeLine + Line
665 NmakeLine = ''
666
667 # section content
668 self._ValueList = ['', '', '']
669 # parse current line, result will be put in self._ValueList
670 self._SectionParser[self._SectionType](self)
671 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
672 self._ItemType = -1
673 Comments = []
674 continue
675 if Comment:
676 Comments.append((Comment, Index + 1))
677 if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:
678 CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)
679 #
680 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
681 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
682 #
683 for Arch, Platform, _ in self._Scope:
684 LastItem = self._Store(self._SectionType,
685 self._ValueList[0],
686 self._ValueList[1],
687 self._ValueList[2],
688 Arch,
689 Platform,
690 self._Owner[-1],
691 self._LineIndex + 1,
692 - 1,
693 self._LineIndex + 1,
694 - 1,
695 0
696 )
697 for Comment, LineNo in Comments:
698 self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,
699 LastItem, LineNo, -1, LineNo, -1, 0)
700 Comments = []
701 SectionComments = []
702 TailComments.extend(SectionComments + Comments)
703 if IsFindBlockComment:
704 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
705 File=self.MetaFile)
706
707 # If there are tail comments in INF file, save to database whatever the comments are
708 for Comment in TailComments:
709 self._Store(MODEL_META_DATA_TAIL_COMMENT, Comment[0], '', '', TAB_COMMON,
710 TAB_COMMON, self._Owner[-1], -1, -1, -1, -1, 0)
711 self._Done()
712
713 ## Data parser for the format in which there's path
714 #
715 # Only path can have macro used. So we need to replace them before use.
716 #
717 def _IncludeParser(self):
718 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
719 self._ValueList[0:len(TokenList)] = TokenList
720 Macros = self._Macros
721 if Macros:
722 for Index in range(0, len(self._ValueList)):
723 Value = self._ValueList[Index]
724 if not Value:
725 continue
726 self._ValueList[Index] = ReplaceMacro(Value, Macros)
727
728 ## Parse [Sources] section
729 #
730 # Only path can have macro used. So we need to replace them before use.
731 #
732 @ParseMacro
733 def _SourceFileParser(self):
734 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
735 self._ValueList[0:len(TokenList)] = TokenList
736 Macros = self._Macros
737 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
738 if 'COMPONENT_TYPE' in Macros:
739 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
740 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
741 if self._Defines['BASE_NAME'] == 'Microcode':
742 pass
743 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
744
745 ## Parse [Binaries] section
746 #
747 # Only path can have macro used. So we need to replace them before use.
748 #
749 @ParseMacro
750 def _BinaryFileParser(self):
751 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
752 if len(TokenList) < 2:
753 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
754 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
755 File=self.MetaFile, Line=self._LineIndex + 1)
756 if not TokenList[0]:
757 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
758 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
759 File=self.MetaFile, Line=self._LineIndex + 1)
760 if not TokenList[1]:
761 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
762 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
763 File=self.MetaFile, Line=self._LineIndex + 1)
764 self._ValueList[0:len(TokenList)] = TokenList
765 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
766
767 ## [nmake] section parser (Edk.x style only)
768 def _NmakeParser(self):
769 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
770 self._ValueList[0:len(TokenList)] = TokenList
771 # remove macros
772 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
773 # remove self-reference in macro setting
774 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
775
776 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
777 @ParseMacro
778 def _PcdParser(self):
779 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
780 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
781 if len(ValueList) != 2:
782 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
783 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
784 File=self.MetaFile, Line=self._LineIndex + 1)
785 self._ValueList[0:1] = ValueList
786 if len(TokenList) > 1:
787 self._ValueList[2] = TokenList[1]
788 if self._ValueList[0] == '' or self._ValueList[1] == '':
789 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
790 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
791 File=self.MetaFile, Line=self._LineIndex + 1)
792
793 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
794 if self._ValueList[2] != '':
795 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
796 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
797 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1)
798 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
799 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1)
800 elif isinstance(InfPcdValueList[0], str) and InfPcdValueList[0].find('$(') >= 0:
801 Value = ReplaceExprMacro(InfPcdValueList[0],self._Macros)
802 if Value != '0':
803 self._ValueList[2] = Value
804 if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:
805 self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType
806 elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:
807 EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",
808 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
809 File=self.MetaFile, Line=self._LineIndex + 1)
810
811 ## [depex] section parser
812 @ParseMacro
813 def _DepexParser(self):
814 self._ValueList[0:1] = [self._CurrentLine]
815
816 _SectionParser = {
817 MODEL_UNKNOWN : MetaFileParser._Skip,
818 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
819 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
820 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules
821 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules
822 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
823 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
824 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules
825 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
826 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
827 MODEL_PCD_FEATURE_FLAG : _PcdParser,
828 MODEL_PCD_DYNAMIC_EX : _PcdParser,
829 MODEL_PCD_DYNAMIC : _PcdParser,
830 MODEL_EFI_SOURCE_FILE : _SourceFileParser,
831 MODEL_EFI_GUID : MetaFileParser._CommonParser,
832 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
833 MODEL_EFI_PPI : MetaFileParser._CommonParser,
834 MODEL_EFI_DEPEX : _DepexParser,
835 MODEL_EFI_BINARY_FILE : _BinaryFileParser,
836 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
837 }
838
839 ## DSC file parser class
840 #
841 # @param FilePath The path of platform description file
842 # @param FileType The raw data of DSC file
843 # @param Table Database used to retrieve module/package information
844 # @param Macros Macros used for replacement in file
845 # @param Owner Owner ID (for sub-section parsing)
846 # @param From ID from which the data comes (for !INCLUDE directive)
847 #
848 class DscParser(MetaFileParser):
849 # DSC file supported data types (one type per section)
850 DataType = {
851 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
852 TAB_DEFAULT_STORES.upper() : MODEL_EFI_DEFAULT_STORES,
853 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
854 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
855 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
856 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
857 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
858 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
859 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
860 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
861 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
862 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
863 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
864 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
865 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
866 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
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 Content = open(str(self.MetaFile), 'r').readlines()
954 except:
955 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
956
957 OwnerId = {}
958
959 Content = self.ProcessMultipleLineCODEValue(Content)
960
961 for Index in range(0, len(Content)):
962 Line = CleanString(Content[Index])
963 # skip empty line
964 if Line == '':
965 continue
966
967 self._CurrentLine = Line
968 self._LineIndex = Index
969 if self._InSubsection and self._Owner[-1] == -1:
970 self._Owner.append(self._LastItem)
971
972 # section header
973 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
974 self._SectionType = MODEL_META_DATA_SECTION_HEADER
975 # subsection ending
976 elif Line[0] == '}' and self._InSubsection:
977 self._InSubsection = False
978 self._SubsectionType = MODEL_UNKNOWN
979 self._SubsectionName = ''
980 self._Owner[-1] = -1
981 OwnerId.clear()
982 continue
983 # subsection header
984 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
985 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
986 # directive line
987 elif Line[0] == '!':
988 TokenList = GetSplitValueList(Line, ' ', 1)
989 if TokenList[0] == TAB_INCLUDE:
990 for Arch, ModuleType, DefaultStore in self._Scope:
991 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
992 self._Owner[-1] = OwnerId[Arch]
993 self._DirectiveParser()
994 else:
995 self._DirectiveParser()
996 continue
997 if Line[0] == TAB_OPTION_START and not self._InSubsection:
998 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)
999
1000 if self._InSubsection:
1001 SectionType = self._SubsectionType
1002 else:
1003 SectionType = self._SectionType
1004 self._ItemType = SectionType
1005
1006 self._ValueList = ['', '', '']
1007 # "SET pcd = pcd_expression" syntax is not supported in Dsc file.
1008 if self._CurrentLine.upper().strip().startswith("SET "):
1009 EdkLogger.error('Parser', FORMAT_INVALID, '''"SET pcd = pcd_expression" syntax is not support in Dsc file''',
1010 ExtraData=self._CurrentLine,
1011 File=self.MetaFile, Line=self._LineIndex + 1)
1012 self._SectionParser[SectionType](self)
1013 if self._ValueList is None:
1014 continue
1015 #
1016 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1017 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1018 #
1019 for Arch, ModuleType, DefaultStore in self._Scope:
1020 Owner = self._Owner[-1]
1021 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
1022 Owner = OwnerId[Arch]
1023 self._LastItem = self._Store(
1024 self._ItemType,
1025 self._ValueList[0],
1026 self._ValueList[1],
1027 self._ValueList[2],
1028 Arch,
1029 ModuleType,
1030 DefaultStore,
1031 Owner,
1032 self._From,
1033 self._LineIndex + 1,
1034 - 1,
1035 self._LineIndex + 1,
1036 - 1,
1037 self._Enabled
1038 )
1039 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
1040 OwnerId[Arch] = self._LastItem
1041
1042 if self._DirectiveStack:
1043 Type, Line, Text = self._DirectiveStack[-1]
1044 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
1045 ExtraData=Text, File=self.MetaFile, Line=Line)
1046 self._Done()
1047
1048 ## <subsection_header> parser
1049 def _SubsectionHeaderParser(self):
1050 self._SubsectionName = self._CurrentLine[1:-1].upper()
1051 if self._SubsectionName in self.DataType:
1052 self._SubsectionType = self.DataType[self._SubsectionName]
1053 else:
1054 self._SubsectionType = MODEL_UNKNOWN
1055 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
1056 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1057 self._ValueList[0] = self._SubsectionName
1058
1059 ## Directive statement parser
1060 def _DirectiveParser(self):
1061 self._ValueList = ['', '', '']
1062 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
1063 self._ValueList[0:len(TokenList)] = TokenList
1064
1065 # Syntax check
1066 DirectiveName = self._ValueList[0].upper()
1067 if DirectiveName not in self.DataType:
1068 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
1069 File=self.MetaFile, Line=self._LineIndex + 1)
1070
1071 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
1072 self._InDirective += 1
1073
1074 if DirectiveName in ['!ENDIF']:
1075 self._InDirective -= 1
1076
1077 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
1078 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
1079 File=self.MetaFile, Line=self._LineIndex + 1,
1080 ExtraData=self._CurrentLine)
1081
1082 ItemType = self.DataType[DirectiveName]
1083 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]
1084 if ItemType == MODEL_META_DATA_INCLUDE:
1085 Scope = self._Scope
1086 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:
1087 Scope = self._Scope
1088 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1089 # Remove all directives between !if and !endif, including themselves
1090 while self._DirectiveStack:
1091 # Remove any !else or !elseif
1092 DirectiveInfo = self._DirectiveStack.pop()
1093 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1094 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1095 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1096 break
1097 else:
1098 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
1099 File=self.MetaFile, Line=self._LineIndex + 1,
1100 ExtraData=self._CurrentLine)
1101 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:
1102 # Break if there's a !else is followed by a !elseif
1103 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
1104 self._DirectiveStack and \
1105 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1106 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
1107 File=self.MetaFile, Line=self._LineIndex + 1,
1108 ExtraData=self._CurrentLine)
1109 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
1110
1111 #
1112 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1113 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1114 #
1115 for Arch, ModuleType, DefaultStore in Scope:
1116 self._LastItem = self._Store(
1117 ItemType,
1118 self._ValueList[0],
1119 self._ValueList[1],
1120 self._ValueList[2],
1121 Arch,
1122 ModuleType,
1123 DefaultStore,
1124 self._Owner[-1],
1125 self._From,
1126 self._LineIndex + 1,
1127 - 1,
1128 self._LineIndex + 1,
1129 - 1,
1130 0
1131 )
1132
1133 ## [defines] section parser
1134 @ParseMacro
1135 def _DefineParser(self):
1136 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1137 self._ValueList[1:len(TokenList)] = TokenList
1138
1139 # Syntax check
1140 if not self._ValueList[1]:
1141 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
1142 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1143 if not self._ValueList[2]:
1144 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
1145 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1146 if (not self._ValueList[1] in self.DefineKeywords and
1147 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):
1148 EdkLogger.error('Parser', FORMAT_INVALID,
1149 "Unknown keyword found: %s. "
1150 "If this is a macro you must "
1151 "add it as a DEFINE in the DSC" % self._ValueList[1],
1152 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1153 if not self._InSubsection:
1154 self._Defines[self._ValueList[1]] = self._ValueList[2]
1155 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
1156
1157 @ParseMacro
1158 def _SkuIdParser(self):
1159 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1160 if len(TokenList) not in (2, 3):
1161 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",
1162 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1163 self._ValueList[0:len(TokenList)] = TokenList
1164 @ParseMacro
1165 def _DefaultStoresParser(self):
1166 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1167 if len(TokenList) != 2:
1168 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",
1169 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1170 self._ValueList[0:len(TokenList)] = TokenList
1171
1172 ## Parse Edk style of library modules
1173 @ParseMacro
1174 def _LibraryInstanceParser(self):
1175 self._ValueList[0] = self._CurrentLine
1176
1177
1178 def _DecodeCODEData(self):
1179 pass
1180 ## PCD sections parser
1181 #
1182 # [PcdsFixedAtBuild]
1183 # [PcdsPatchableInModule]
1184 # [PcdsFeatureFlag]
1185 # [PcdsDynamicEx
1186 # [PcdsDynamicExDefault]
1187 # [PcdsDynamicExVpd]
1188 # [PcdsDynamicExHii]
1189 # [PcdsDynamic]
1190 # [PcdsDynamicDefault]
1191 # [PcdsDynamicVpd]
1192 # [PcdsDynamicHii]
1193 #
1194 @ParseMacro
1195 def _PcdParser(self):
1196 if self._PcdDataTypeCODE:
1197 self._PcdCodeValue = self._PcdCodeValue + "\n " + self._CurrentLine
1198 if self._CurrentLine.endswith(")}"):
1199 self._CurrentLine = "|".join((self._CurrentPcdName, self._PcdCodeValue))
1200 self._PcdDataTypeCODE = False
1201 self._PcdCodeValue = ""
1202 else:
1203 self._ValueList = None
1204 return
1205 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1206 self._CurrentPcdName = TokenList[0]
1207 if len(TokenList) == 2 and TokenList[1].strip().startswith("{CODE"):
1208 self._PcdDataTypeCODE = True
1209 self._PcdCodeValue = TokenList[1].strip()
1210
1211 if self._PcdDataTypeCODE:
1212 if self._CurrentLine.endswith(")}"):
1213 self._PcdDataTypeCODE = False
1214 self._PcdCodeValue = ""
1215 else:
1216 self._ValueList = None
1217 return
1218 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1219 PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)
1220 if len(PcdNameTockens) == 2:
1221 self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]
1222 elif len(PcdNameTockens) == 3:
1223 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]
1224 elif len(PcdNameTockens) > 3:
1225 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])
1226 if len(TokenList) == 2:
1227 self._ValueList[2] = TokenList[1]
1228 if self._ValueList[0] == '' or self._ValueList[1] == '':
1229 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1230 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1231 File=self.MetaFile, Line=self._LineIndex + 1)
1232 if self._ValueList[2] == '':
1233 #
1234 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default
1235 #
1236 if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
1237 return
1238 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
1239 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1240 File=self.MetaFile, Line=self._LineIndex + 1)
1241
1242 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1243 ValueList = GetSplitValueList(self._ValueList[2])
1244 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \
1245 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
1246 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
1247 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1248
1249 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string
1250 if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:
1251 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1252 if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:
1253 EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",
1254 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1255
1256 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1257 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1258 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
1259 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
1260 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
1261 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
1262
1263
1264 ## [components] section parser
1265 @ParseMacro
1266 def _ComponentParser(self):
1267 if self._CurrentLine[-1] == '{':
1268 self._ValueList[0] = self._CurrentLine[0:-1].strip()
1269 self._InSubsection = True
1270 self._SubsectionType = MODEL_UNKNOWN
1271 else:
1272 self._ValueList[0] = self._CurrentLine
1273
1274 ## [LibraryClasses] section
1275 @ParseMacro
1276 def _LibraryClassParser(self):
1277 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1278 if len(TokenList) < 2:
1279 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
1280 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1281 File=self.MetaFile, Line=self._LineIndex + 1)
1282 if TokenList[0] == '':
1283 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
1284 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1285 File=self.MetaFile, Line=self._LineIndex + 1)
1286 if TokenList[1] == '':
1287 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
1288 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1289 File=self.MetaFile, Line=self._LineIndex + 1)
1290
1291 self._ValueList[0:len(TokenList)] = TokenList
1292
1293 def _CompponentSourceOverridePathParser(self):
1294 self._ValueList[0] = self._CurrentLine
1295
1296 ## [BuildOptions] section parser
1297 @ParseMacro
1298 def _BuildOptionParser(self):
1299 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
1300 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1301 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
1302 if len(TokenList2) == 2:
1303 self._ValueList[0] = TokenList2[0] # toolchain family
1304 self._ValueList[1] = TokenList2[1] # keys
1305 else:
1306 self._ValueList[1] = TokenList[0]
1307 if len(TokenList) == 2: # value
1308 self._ValueList[2] = TokenList[1]
1309
1310 if self._ValueList[1].count('_') != 4:
1311 EdkLogger.error(
1312 'Parser',
1313 FORMAT_INVALID,
1314 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
1315 ExtraData=self._CurrentLine,
1316 File=self.MetaFile,
1317 Line=self._LineIndex + 1
1318 )
1319
1320 ## Override parent's method since we'll do all macro replacements in parser
1321 @property
1322 def _Macros(self):
1323 Macros = {}
1324 Macros.update(self._FileLocalMacros)
1325 Macros.update(self._GetApplicableSectionMacro())
1326 Macros.update(GlobalData.gEdkGlobal)
1327 Macros.update(GlobalData.gPlatformDefines)
1328 Macros.update(GlobalData.gCommandLineDefines)
1329 # PCD cannot be referenced in macro definition
1330 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
1331 Macros.update(self._Symbols)
1332 if GlobalData.BuildOptionPcd:
1333 for Item in GlobalData.BuildOptionPcd:
1334 if isinstance(Item, tuple):
1335 continue
1336 PcdName, TmpValue = Item.split("=")
1337 TmpValue = BuildOptionValue(TmpValue, self._GuidDict)
1338 Macros[PcdName.strip()] = TmpValue
1339 return Macros
1340
1341 def _PostProcess(self):
1342 Processer = {
1343 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,
1344 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,
1345 MODEL_META_DATA_HEADER : self.__ProcessDefine,
1346 MODEL_META_DATA_DEFINE : self.__ProcessDefine,
1347 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,
1348 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,
1349 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,
1350 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,
1351 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,
1352 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,
1353 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,
1354 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,
1355 MODEL_EFI_SKU_ID : self.__ProcessSkuId,
1356 MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,
1357 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,
1358 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,
1359 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,
1360 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,
1361 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,
1362 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,
1363 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,
1364 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,
1365 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,
1366 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,
1367 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,
1368 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,
1369 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,
1370 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,
1371 MODEL_UNKNOWN : self._Skip,
1372 MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,
1373 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,
1374 }
1375
1376 self._Table = MetaFileStorage(self._RawTable.DB, self.MetaFile, MODEL_FILE_DSC, True)
1377 self._DirectiveStack = []
1378 self._DirectiveEvalStack = []
1379 self._FileWithError = self.MetaFile
1380 self._FileLocalMacros = {}
1381 self._SectionsMacroDict.clear()
1382 GlobalData.gPlatformDefines = {}
1383
1384 # Get all macro and PCD which has straitforward value
1385 self.__RetrievePcdValue()
1386 self._Content = self._RawTable.GetAll()
1387 self._ContentIndex = 0
1388 self._InSubsection = False
1389 while self._ContentIndex < len(self._Content) :
1390 Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \
1391 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
1392
1393 if self._From < 0:
1394 self._FileWithError = self.MetaFile
1395
1396 self._ContentIndex += 1
1397
1398 self._Scope = [[S1, S2, S3]]
1399 #
1400 # For !include directive, handle it specially,
1401 # merge arch and module type in case of duplicate items
1402 #
1403 while self._ItemType == MODEL_META_DATA_INCLUDE:
1404 if self._ContentIndex >= len(self._Content):
1405 break
1406 Record = self._Content[self._ContentIndex]
1407 if LineStart == Record[10] and LineEnd == Record[12]:
1408 if [Record[5], Record[6], Record[7]] not in self._Scope:
1409 self._Scope.append([Record[5], Record[6], Record[7]])
1410 self._ContentIndex += 1
1411 else:
1412 break
1413
1414 self._LineIndex = LineStart - 1
1415 self._ValueList = [V1, V2, V3]
1416
1417 if Owner > 0 and Owner in self._IdMapping:
1418 self._InSubsection = True
1419 else:
1420 self._InSubsection = False
1421 try:
1422 Processer[self._ItemType]()
1423 except EvaluationException as Excpt:
1424 #
1425 # Only catch expression evaluation error here. We need to report
1426 # the precise number of line on which the error occurred
1427 #
1428 if hasattr(Excpt, 'Pcd'):
1429 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
1430 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
1431 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
1432 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1433 " of the DSC file, and it is currently defined in this section:"
1434 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
1435 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1436 Line=self._LineIndex + 1)
1437 else:
1438 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
1439 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1440 Line=self._LineIndex + 1)
1441 else:
1442 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1443 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1444 Line=self._LineIndex + 1)
1445 except MacroException as Excpt:
1446 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
1447 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1448 Line=self._LineIndex + 1)
1449
1450 if self._ValueList is None:
1451 continue
1452
1453 NewOwner = self._IdMapping.get(Owner, -1)
1454 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
1455 self._LastItem = self._Store(
1456 self._ItemType,
1457 self._ValueList[0],
1458 self._ValueList[1],
1459 self._ValueList[2],
1460 S1,
1461 S2,
1462 S3,
1463 NewOwner,
1464 self._From,
1465 self._LineIndex + 1,
1466 - 1,
1467 self._LineIndex + 1,
1468 - 1,
1469 self._Enabled
1470 )
1471 self._IdMapping[Id] = self._LastItem
1472
1473 GlobalData.gPlatformDefines.update(self._FileLocalMacros)
1474 self._PostProcessed = True
1475 self._Content = None
1476 def _ProcessError(self):
1477 if not self._Enabled:
1478 return
1479 EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)
1480
1481 def __ProcessSectionHeader(self):
1482 self._SectionName = self._ValueList[0]
1483 if self._SectionName in self.DataType:
1484 self._SectionType = self.DataType[self._SectionName]
1485 else:
1486 self._SectionType = MODEL_UNKNOWN
1487
1488 def __ProcessSubsectionHeader(self):
1489 self._SubsectionName = self._ValueList[0]
1490 if self._SubsectionName in self.DataType:
1491 self._SubsectionType = self.DataType[self._SubsectionName]
1492 else:
1493 self._SubsectionType = MODEL_UNKNOWN
1494
1495 def __RetrievePcdValue(self):
1496 Content = open(str(self.MetaFile), 'r').readlines()
1497 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
1498 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
1499 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
1500 MODEL_PCD_DYNAMIC_EX_VPD):
1501 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
1502 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:
1503 Name = TokenSpaceGuid + '.' + PcdName
1504 if Name not in GlobalData.gPlatformOtherPcds:
1505 PcdLine = Line
1506 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
1507 Line -= 1
1508 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
1509
1510 def __ProcessDefine(self):
1511 if not self._Enabled:
1512 return
1513
1514 Type, Name, Value = self._ValueList
1515 Value = ReplaceMacro(Value, self._Macros, False)
1516 #
1517 # If it is <Defines>, return
1518 #
1519 if self._InSubsection:
1520 self._ValueList = [Type, Name, Value]
1521 return
1522
1523 if self._ItemType == MODEL_META_DATA_DEFINE:
1524 if self._SectionType == MODEL_META_DATA_HEADER:
1525 self._FileLocalMacros[Name] = Value
1526 else:
1527 self._ConstructSectionMacroDict(Name, Value)
1528 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
1529 GlobalData.gEdkGlobal[Name] = Value
1530
1531 #
1532 # Keyword in [Defines] section can be used as Macros
1533 #
1534 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
1535 self._FileLocalMacros[Name] = Value
1536
1537 self._ValueList = [Type, Name, Value]
1538
1539 def __ProcessDirective(self):
1540 Result = None
1541 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1542 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
1543 Macros = self._Macros
1544 Macros.update(GlobalData.gGlobalDefines)
1545 try:
1546 Result = ValueExpression(self._ValueList[1], Macros)()
1547 except SymbolNotFound as Exc:
1548 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1549 Result = False
1550 except WrnExpression as Excpt:
1551 #
1552 # Catch expression evaluation warning here. We need to report
1553 # the precise number of line and return the evaluation result
1554 #
1555 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
1556 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1557 Line=self._LineIndex + 1)
1558 Result = Excpt.result
1559
1560 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1561 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1562 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1563 self._DirectiveStack.append(self._ItemType)
1564 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
1565 Result = bool(Result)
1566 else:
1567 Macro = self._ValueList[1]
1568 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
1569 Result = Macro in self._Macros
1570 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
1571 Result = not Result
1572 self._DirectiveEvalStack.append(Result)
1573 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
1574 self._DirectiveStack.append(self._ItemType)
1575 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1576 self._DirectiveEvalStack.append(bool(Result))
1577 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1578 self._DirectiveStack.append(self._ItemType)
1579 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1580 self._DirectiveEvalStack.append(True)
1581 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1582 # Back to the nearest !if/!ifdef/!ifndef
1583 while self._DirectiveStack:
1584 self._DirectiveEvalStack.pop()
1585 Directive = self._DirectiveStack.pop()
1586 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1587 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1588 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1589 break
1590 elif self._ItemType == MODEL_META_DATA_INCLUDE:
1591 # The included file must be relative to workspace or same directory as DSC file
1592 __IncludeMacros = {}
1593 #
1594 # Allow using system environment variables in path after !include
1595 #
1596 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
1597 #
1598 # Allow using MACROs comes from [Defines] section to keep compatible.
1599 #
1600 __IncludeMacros.update(self._Macros)
1601
1602 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
1603 #
1604 # First search the include file under the same directory as DSC file
1605 #
1606 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
1607 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
1608 if ErrorCode != 0:
1609 #
1610 # Also search file under the WORKSPACE directory
1611 #
1612 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
1613 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
1614 if ErrorCode != 0:
1615 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
1616 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
1617
1618 self._FileWithError = IncludedFile1
1619
1620 FromItem = self._Content[self._ContentIndex - 1][0]
1621 if self._InSubsection:
1622 Owner = self._Content[self._ContentIndex - 1][8]
1623 else:
1624 Owner = self._Content[self._ContentIndex - 1][0]
1625 IncludedFileTable = MetaFileStorage(self._RawTable.DB, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)
1626 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,
1627 Owner=Owner, From=FromItem)
1628
1629 self.IncludedFiles.add (IncludedFile1)
1630
1631 # set the parser status with current status
1632 Parser._SectionName = self._SectionName
1633 Parser._SubsectionType = self._SubsectionType
1634 Parser._InSubsection = self._InSubsection
1635 Parser._SectionType = self._SectionType
1636 Parser._Scope = self._Scope
1637 Parser._Enabled = self._Enabled
1638 # Parse the included file
1639 Parser.StartParse()
1640 # Insert all records in the table for the included file into dsc file table
1641 Records = IncludedFileTable.GetAll()
1642 if Records:
1643 self._Content[self._ContentIndex:self._ContentIndex] = Records
1644 self._Content.pop(self._ContentIndex - 1)
1645 self._ValueList = None
1646 self._ContentIndex -= 1
1647
1648 def __ProcessSkuId(self):
1649 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1650 for Value in self._ValueList]
1651 def __ProcessDefaultStores(self):
1652 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1653 for Value in self._ValueList]
1654
1655 def __ProcessLibraryInstance(self):
1656 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
1657
1658 def __ProcessLibraryClass(self):
1659 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
1660
1661 def __ProcessPcd(self):
1662 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
1663 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
1664 return
1665
1666 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
1667 if not Valid:
1668 if self._ItemType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
1669 if ValList[1] != TAB_VOID and StructPattern.match(ValList[1]) is None and ValList[2]:
1670 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect. The datum type info should be VOID* or a valid struct name.", File=self._FileWithError,
1671 Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1672 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,
1673 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1674 PcdValue = ValList[Index]
1675 if PcdValue and "." not in self._ValueList[0]:
1676 try:
1677 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
1678 except WrnExpression as Value:
1679 ValList[Index] = Value.result
1680 except:
1681 pass
1682
1683 if ValList[Index] == 'True':
1684 ValList[Index] = '1'
1685 if ValList[Index] == 'False':
1686 ValList[Index] = '0'
1687
1688 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):
1689 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1690 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1691 try:
1692 self._ValueList[2] = '|'.join(ValList)
1693 except Exception:
1694 print(ValList)
1695
1696 def __ProcessComponent(self):
1697 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1698
1699 def __ProcessSourceOverridePath(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_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,
1728 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1729 MODEL_UNKNOWN : MetaFileParser._Skip,
1730 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
1731 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1732 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1733 }
1734
1735 ## DEC file parser class
1736 #
1737 # @param FilePath The path of platform description file
1738 # @param FileType The raw data of DSC file
1739 # @param Table Database used to retrieve module/package information
1740 # @param Macros Macros used for replacement in file
1741 #
1742 class DecParser(MetaFileParser):
1743 # DEC file supported data types (one type per section)
1744 DataType = {
1745 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1746 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1747 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1748 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1749 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1750 TAB_PPIS.upper() : MODEL_EFI_PPI,
1751 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1752 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1753 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1754 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1755 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1756 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1757 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
1758 }
1759
1760 ## Constructor of DecParser
1761 #
1762 # Initialize object of DecParser
1763 #
1764 # @param FilePath The path of platform description file
1765 # @param FileType The raw data of DSC file
1766 # @param Arch Default Arch value for filtering sections
1767 # @param Table Database used to retrieve module/package information
1768 #
1769 def __init__(self, FilePath, FileType, Arch, Table):
1770 # prevent re-initialization
1771 if hasattr(self, "_Table"):
1772 return
1773 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)
1774 self._Comments = []
1775 self._Version = 0x00010005 # Only EDK2 dec file is supported
1776 self._AllPCDs = [] # Only for check duplicate PCD
1777 self._AllPcdDict = {}
1778
1779 self._CurrentStructurePcdName = ""
1780 self._include_flag = False
1781 self._package_flag = False
1782
1783 self._RestofValue = ""
1784
1785 ## Parser starter
1786 def Start(self):
1787 Content = ''
1788 try:
1789 Content = open(str(self.MetaFile), 'r').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