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