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