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