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