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