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