Sync BaseTool trunk (version r2601) into EDKII BaseTools.
[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 OwnerId = {}
831 for Index in range(0, len(Content)):
832 Line = CleanString(Content[Index])
833 # skip empty line
834 if Line == '':
835 continue
836
837 self._CurrentLine = Line
838 self._LineIndex = Index
839 if self._InSubsection and self._Owner[-1] == -1:
840 self._Owner.append(self._LastItem)
841
842 # section header
843 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
844 self._SectionType = MODEL_META_DATA_SECTION_HEADER
845 # subsection ending
846 elif Line[0] == '}' and self._InSubsection:
847 self._InSubsection = False
848 self._SubsectionType = MODEL_UNKNOWN
849 self._SubsectionName = ''
850 self._Owner[-1] = -1
851 OwnerId = {}
852 continue
853 # subsection header
854 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
855 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
856 # directive line
857 elif Line[0] == '!':
858 self._DirectiveParser()
859 continue
860
861 if self._InSubsection:
862 SectionType = self._SubsectionType
863 else:
864 SectionType = self._SectionType
865 self._ItemType = SectionType
866
867 self._ValueList = ['', '', '']
868 self._SectionParser[SectionType](self)
869 if self._ValueList == None:
870 continue
871 #
872 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
873 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
874 #
875 for Arch, ModuleType in self._Scope:
876 Owner = self._Owner[-1]
877 if self._SubsectionType != MODEL_UNKNOWN:
878 Owner = OwnerId[Arch]
879 self._LastItem = self._Store(
880 self._ItemType,
881 self._ValueList[0],
882 self._ValueList[1],
883 self._ValueList[2],
884 Arch,
885 ModuleType,
886 Owner,
887 self._From,
888 self._LineIndex + 1,
889 - 1,
890 self._LineIndex + 1,
891 - 1,
892 self._Enabled
893 )
894 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
895 OwnerId[Arch] = self._LastItem
896
897 if self._DirectiveStack:
898 Type, Line, Text = self._DirectiveStack[-1]
899 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
900 ExtraData=Text, File=self.MetaFile, Line=Line)
901 self._Done()
902
903 ## <subsection_header> parser
904 def _SubsectionHeaderParser(self):
905 self._SubsectionName = self._CurrentLine[1:-1].upper()
906 if self._SubsectionName in self.DataType:
907 self._SubsectionType = self.DataType[self._SubsectionName]
908 else:
909 self._SubsectionType = MODEL_UNKNOWN
910 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
911 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
912 self._ValueList[0] = self._SubsectionName
913
914 ## Directive statement parser
915 def _DirectiveParser(self):
916 self._ValueList = ['', '', '']
917 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
918 self._ValueList[0:len(TokenList)] = TokenList
919
920 # Syntax check
921 DirectiveName = self._ValueList[0].upper()
922 if DirectiveName not in self.DataType:
923 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
924 File=self.MetaFile, Line=self._LineIndex + 1)
925
926 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
927 self._InDirective += 1
928
929 if DirectiveName in ['!ENDIF']:
930 self._InDirective -= 1
931
932 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
933 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
934 File=self.MetaFile, Line=self._LineIndex + 1,
935 ExtraData=self._CurrentLine)
936
937 ItemType = self.DataType[DirectiveName]
938 Scope = [['COMMON', 'COMMON']]
939 if ItemType == MODEL_META_DATA_INCLUDE:
940 Scope = self._Scope
941 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
942 # Remove all directives between !if and !endif, including themselves
943 while self._DirectiveStack:
944 # Remove any !else or !elseif
945 DirectiveInfo = self._DirectiveStack.pop()
946 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
947 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
948 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
949 break
950 else:
951 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
952 File=self.MetaFile, Line=self._LineIndex + 1,
953 ExtraData=self._CurrentLine)
954 elif ItemType != MODEL_META_DATA_INCLUDE:
955 # Break if there's a !else is followed by a !elseif
956 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
957 self._DirectiveStack and \
958 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
959 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
960 File=self.MetaFile, Line=self._LineIndex + 1,
961 ExtraData=self._CurrentLine)
962 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
963 elif self._From > 0:
964 EdkLogger.error('Parser', FORMAT_INVALID,
965 "No '!include' allowed in included file",
966 ExtraData=self._CurrentLine, File=self.MetaFile,
967 Line=self._LineIndex + 1)
968
969 #
970 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
971 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
972 #
973 for Arch, ModuleType in Scope:
974 self._LastItem = self._Store(
975 ItemType,
976 self._ValueList[0],
977 self._ValueList[1],
978 self._ValueList[2],
979 Arch,
980 ModuleType,
981 self._Owner[-1],
982 self._From,
983 self._LineIndex + 1,
984 - 1,
985 self._LineIndex + 1,
986 - 1,
987 0
988 )
989
990 ## [defines] section parser
991 @ParseMacro
992 def _DefineParser(self):
993 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
994 self._ValueList[1:len(TokenList)] = TokenList
995
996 # Syntax check
997 if not self._ValueList[1]:
998 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
999 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1000 if not self._ValueList[2]:
1001 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
1002 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1003 if not self._ValueList[1] in self.DefineKeywords:
1004 EdkLogger.error('Parser', FORMAT_INVALID,
1005 "Unknown keyword found: %s. "
1006 "If this is a macro you must "
1007 "add it as a DEFINE in the DSC" % self._ValueList[1],
1008 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1009 self._Defines[self._ValueList[1]] = self._ValueList[2]
1010 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
1011
1012 @ParseMacro
1013 def _SkuIdParser(self):
1014 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1015 if len(TokenList) != 2:
1016 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",
1017 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1018 self._ValueList[0:len(TokenList)] = TokenList
1019
1020 ## Parse Edk style of library modules
1021 @ParseMacro
1022 def _LibraryInstanceParser(self):
1023 self._ValueList[0] = self._CurrentLine
1024
1025 ## PCD sections parser
1026 #
1027 # [PcdsFixedAtBuild]
1028 # [PcdsPatchableInModule]
1029 # [PcdsFeatureFlag]
1030 # [PcdsDynamicEx
1031 # [PcdsDynamicExDefault]
1032 # [PcdsDynamicExVpd]
1033 # [PcdsDynamicExHii]
1034 # [PcdsDynamic]
1035 # [PcdsDynamicDefault]
1036 # [PcdsDynamicVpd]
1037 # [PcdsDynamicHii]
1038 #
1039 @ParseMacro
1040 def _PcdParser(self):
1041 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1042 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1043 if len(TokenList) == 2:
1044 self._ValueList[2] = TokenList[1]
1045 if self._ValueList[0] == '' or self._ValueList[1] == '':
1046 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1047 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1048 File=self.MetaFile, Line=self._LineIndex + 1)
1049 if self._ValueList[2] == '':
1050 #
1051 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1052 #
1053 if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
1054 return
1055 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
1056 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1057 File=self.MetaFile, Line=self._LineIndex + 1)
1058
1059 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1060 ValueList = GetSplitValueList(self._ValueList[2])
1061 if len(ValueList) > 1 and ValueList[1] != TAB_VOID \
1062 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
1063 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
1064 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1065
1066 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1067 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1068 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
1069 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
1070 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
1071 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
1072
1073
1074 ## [components] section parser
1075 @ParseMacro
1076 def _ComponentParser(self):
1077 if self._CurrentLine[-1] == '{':
1078 self._ValueList[0] = self._CurrentLine[0:-1].strip()
1079 self._InSubsection = True
1080 else:
1081 self._ValueList[0] = self._CurrentLine
1082
1083 ## [LibraryClasses] section
1084 @ParseMacro
1085 def _LibraryClassParser(self):
1086 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1087 if len(TokenList) < 2:
1088 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
1089 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1090 File=self.MetaFile, Line=self._LineIndex + 1)
1091 if TokenList[0] == '':
1092 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
1093 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1094 File=self.MetaFile, Line=self._LineIndex + 1)
1095 if TokenList[1] == '':
1096 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
1097 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1098 File=self.MetaFile, Line=self._LineIndex + 1)
1099
1100 self._ValueList[0:len(TokenList)] = TokenList
1101
1102 def _CompponentSourceOverridePathParser(self):
1103 self._ValueList[0] = self._CurrentLine
1104
1105 ## [BuildOptions] section parser
1106 @ParseMacro
1107 def _BuildOptionParser(self):
1108 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
1109 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1110 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
1111 if len(TokenList2) == 2:
1112 self._ValueList[0] = TokenList2[0] # toolchain family
1113 self._ValueList[1] = TokenList2[1] # keys
1114 else:
1115 self._ValueList[1] = TokenList[0]
1116 if len(TokenList) == 2: # value
1117 self._ValueList[2] = TokenList[1]
1118
1119 if self._ValueList[1].count('_') != 4:
1120 EdkLogger.error(
1121 'Parser',
1122 FORMAT_INVALID,
1123 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
1124 ExtraData=self._CurrentLine,
1125 File=self.MetaFile,
1126 Line=self._LineIndex + 1
1127 )
1128
1129 ## Override parent's method since we'll do all macro replacements in parser
1130 def _GetMacros(self):
1131 Macros = {}
1132 Macros.update(self._FileLocalMacros)
1133 Macros.update(self._GetApplicableSectionMacro())
1134 Macros.update(GlobalData.gEdkGlobal)
1135 Macros.update(GlobalData.gPlatformDefines)
1136 Macros.update(GlobalData.gCommandLineDefines)
1137 # PCD cannot be referenced in macro definition
1138 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
1139 Macros.update(self._Symbols)
1140 return Macros
1141
1142 def _PostProcess(self):
1143 Processer = {
1144 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,
1145 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,
1146 MODEL_META_DATA_HEADER : self.__ProcessDefine,
1147 MODEL_META_DATA_DEFINE : self.__ProcessDefine,
1148 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,
1149 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,
1150 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,
1151 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,
1152 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,
1153 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,
1154 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,
1155 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,
1156 MODEL_EFI_SKU_ID : self.__ProcessSkuId,
1157 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,
1158 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,
1159 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,
1160 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,
1161 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,
1162 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,
1163 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,
1164 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,
1165 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,
1166 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,
1167 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,
1168 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,
1169 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,
1170 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,
1171 MODEL_UNKNOWN : self._Skip,
1172 MODEL_META_DATA_USER_EXTENSION : self._Skip,
1173 }
1174
1175 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)
1176 self._Table.Create()
1177 self._DirectiveStack = []
1178 self._DirectiveEvalStack = []
1179 self._FileWithError = self.MetaFile
1180 self._FileLocalMacros = {}
1181 self._SectionsMacroDict = {}
1182 GlobalData.gPlatformDefines = {}
1183
1184 # Get all macro and PCD which has straitforward value
1185 self.__RetrievePcdValue()
1186 self._Content = self._RawTable.GetAll()
1187 self._ContentIndex = 0
1188 while self._ContentIndex < len(self._Content) :
1189 Id, self._ItemType, V1, V2, V3, S1, S2, Owner, self._From, \
1190 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
1191
1192 if self._From < 0:
1193 self._FileWithError = self.MetaFile
1194
1195 self._ContentIndex += 1
1196
1197 self._Scope = [[S1, S2]]
1198 #
1199 # For !include directive, handle it specially,
1200 # merge arch and module type in case of duplicate items
1201 #
1202 while self._ItemType == MODEL_META_DATA_INCLUDE:
1203 if self._ContentIndex >= len(self._Content):
1204 break
1205 Record = self._Content[self._ContentIndex]
1206 if LineStart == Record[9] and LineEnd == Record[11]:
1207 if [Record[5], Record[6]] not in self._Scope:
1208 self._Scope.append([Record[5], Record[6]])
1209 self._ContentIndex += 1
1210 else:
1211 break
1212
1213 self._LineIndex = LineStart - 1
1214 self._ValueList = [V1, V2, V3]
1215
1216 try:
1217 Processer[self._ItemType]()
1218 except EvaluationException, Excpt:
1219 #
1220 # Only catch expression evaluation error here. We need to report
1221 # the precise number of line on which the error occurred
1222 #
1223 if hasattr(Excpt, 'Pcd'):
1224 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
1225 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
1226 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
1227 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1228 " of the DSC file, and it is currently defined in this section:"
1229 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
1230 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1231 Line=self._LineIndex + 1)
1232 else:
1233 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
1234 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1235 Line=self._LineIndex + 1)
1236 else:
1237 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1238 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1239 Line=self._LineIndex + 1)
1240 except MacroException, Excpt:
1241 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
1242 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1243 Line=self._LineIndex + 1)
1244
1245 if self._ValueList == None:
1246 continue
1247
1248 NewOwner = self._IdMapping.get(Owner, -1)
1249 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
1250 self._LastItem = self._Store(
1251 self._ItemType,
1252 self._ValueList[0],
1253 self._ValueList[1],
1254 self._ValueList[2],
1255 S1,
1256 S2,
1257 NewOwner,
1258 self._From,
1259 self._LineIndex + 1,
1260 - 1,
1261 self._LineIndex + 1,
1262 - 1,
1263 self._Enabled
1264 )
1265 self._IdMapping[Id] = self._LastItem
1266
1267 GlobalData.gPlatformDefines.update(self._FileLocalMacros)
1268 self._PostProcessed = True
1269 self._Content = None
1270
1271 def __ProcessSectionHeader(self):
1272 self._SectionName = self._ValueList[0]
1273 if self._SectionName in self.DataType:
1274 self._SectionType = self.DataType[self._SectionName]
1275 else:
1276 self._SectionType = MODEL_UNKNOWN
1277
1278 def __ProcessSubsectionHeader(self):
1279 self._SubsectionName = self._ValueList[0]
1280 if self._SubsectionName in self.DataType:
1281 self._SubsectionType = self.DataType[self._SubsectionName]
1282 else:
1283 self._SubsectionType = MODEL_UNKNOWN
1284
1285 def __RetrievePcdValue(self):
1286 Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem= -1.0)
1287 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
1288 Name = TokenSpaceGuid + '.' + PcdName
1289 ValList, Valid, Index = AnalyzeDscPcd(Value, MODEL_PCD_FEATURE_FLAG)
1290 self._Symbols[Name] = ValList[Index]
1291
1292 Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem= -1.0)
1293 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
1294 Name = TokenSpaceGuid + '.' + PcdName
1295 ValList, Valid, Index = AnalyzeDscPcd(Value, MODEL_PCD_FIXED_AT_BUILD)
1296 self._Symbols[Name] = ValList[Index]
1297
1298 Content = open(str(self.MetaFile), 'r').readlines()
1299 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
1300 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
1301 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
1302 MODEL_PCD_DYNAMIC_EX_VPD):
1303 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
1304 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
1305 Name = TokenSpaceGuid + '.' + PcdName
1306 if Name not in GlobalData.gPlatformOtherPcds:
1307 PcdLine = Line
1308 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
1309 Line -= 1
1310 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
1311
1312 def __ProcessDefine(self):
1313 if not self._Enabled:
1314 return
1315
1316 Type, Name, Value = self._ValueList
1317 Value = ReplaceMacro(Value, self._Macros, False)
1318 if self._ItemType == MODEL_META_DATA_DEFINE:
1319 if self._SectionType == MODEL_META_DATA_HEADER:
1320 self._FileLocalMacros[Name] = Value
1321 else:
1322 self._ConstructSectionMacroDict(Name, Value)
1323 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
1324 GlobalData.gEdkGlobal[Name] = Value
1325
1326 #
1327 # Keyword in [Defines] section can be used as Macros
1328 #
1329 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
1330 self._FileLocalMacros[Name] = Value
1331
1332 self._ValueList = [Type, Name, Value]
1333
1334 def __ProcessDirective(self):
1335 Result = None
1336 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1337 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
1338 Macros = self._Macros
1339 Macros.update(GlobalData.gGlobalDefines)
1340 try:
1341 Result = ValueExpression(self._ValueList[1], Macros)()
1342 except SymbolNotFound, Exc:
1343 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1344 Result = False
1345 except WrnExpression, Excpt:
1346 #
1347 # Catch expression evaluation warning here. We need to report
1348 # the precise number of line and return the evaluation result
1349 #
1350 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
1351 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1352 Line=self._LineIndex + 1)
1353 Result = Excpt.result
1354
1355 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1356 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1357 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1358 self._DirectiveStack.append(self._ItemType)
1359 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
1360 Result = bool(Result)
1361 else:
1362 Macro = self._ValueList[1]
1363 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
1364 Result = Macro in self._Macros
1365 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
1366 Result = not Result
1367 self._DirectiveEvalStack.append(Result)
1368 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
1369 self._DirectiveStack.append(self._ItemType)
1370 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1371 self._DirectiveEvalStack.append(bool(Result))
1372 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1373 self._DirectiveStack.append(self._ItemType)
1374 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1375 self._DirectiveEvalStack.append(True)
1376 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1377 # Back to the nearest !if/!ifdef/!ifndef
1378 while self._DirectiveStack:
1379 self._DirectiveEvalStack.pop()
1380 Directive = self._DirectiveStack.pop()
1381 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1382 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1383 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1384 break
1385 elif self._ItemType == MODEL_META_DATA_INCLUDE:
1386 # The included file must be relative to workspace or same directory as DSC file
1387 __IncludeMacros = {}
1388 #
1389 # Allow using system environment variables in path after !include
1390 #
1391 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
1392 if "ECP_SOURCE" in GlobalData.gGlobalDefines.keys():
1393 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']
1394 #
1395 # During GenFds phase call DSC parser, will go into this branch.
1396 #
1397 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines.keys():
1398 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']
1399
1400 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']
1401 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']
1402 #
1403 # Allow using MACROs comes from [Defines] section to keep compatible.
1404 #
1405 __IncludeMacros.update(self._Macros)
1406
1407 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
1408 #
1409 # First search the include file under the same directory as DSC file
1410 #
1411 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
1412 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
1413 if ErrorCode != 0:
1414 #
1415 # Also search file under the WORKSPACE directory
1416 #
1417 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
1418 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
1419 if ErrorCode != 0:
1420 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
1421 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
1422
1423 self._FileWithError = IncludedFile1
1424
1425 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False)
1426 Owner = self._Content[self._ContentIndex - 1][0]
1427 Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable,
1428 Owner=Owner, From=Owner)
1429
1430 # set the parser status with current status
1431 Parser._SectionName = self._SectionName
1432 Parser._SectionType = self._SectionType
1433 Parser._Scope = self._Scope
1434 Parser._Enabled = self._Enabled
1435 # Parse the included file
1436 Parser.Start()
1437
1438 # update current status with sub-parser's status
1439 self._SectionName = Parser._SectionName
1440 self._SectionType = Parser._SectionType
1441 self._Scope = Parser._Scope
1442 self._Enabled = Parser._Enabled
1443
1444 # Insert all records in the table for the included file into dsc file table
1445 Records = IncludedFileTable.GetAll()
1446 if Records:
1447 self._Content[self._ContentIndex:self._ContentIndex] = Records
1448 self._Content.pop(self._ContentIndex - 1)
1449 self._ValueList = None
1450 self._ContentIndex -= 1
1451
1452 def __ProcessSkuId(self):
1453 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1454 for Value in self._ValueList]
1455
1456 def __ProcessLibraryInstance(self):
1457 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
1458
1459 def __ProcessLibraryClass(self):
1460 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
1461
1462 def __ProcessPcd(self):
1463 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
1464 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
1465 return
1466
1467 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
1468 if not Valid:
1469 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex+1,
1470 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1471 PcdValue = ValList[Index]
1472 if PcdValue:
1473 try:
1474 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
1475 except WrnExpression, Value:
1476 ValList[Index] = Value.result
1477
1478 if ValList[Index] == 'True':
1479 ValList[Index] = '1'
1480 if ValList[Index] == 'False':
1481 ValList[Index] = '0'
1482
1483 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1484 self._ValueList[2] = '|'.join(ValList)
1485
1486 def __ProcessComponent(self):
1487 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1488
1489 def __ProcessSourceOverridePath(self):
1490 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1491
1492 def __ProcessBuildOption(self):
1493 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
1494 for Value in self._ValueList]
1495
1496 _SectionParser = {
1497 MODEL_META_DATA_HEADER : _DefineParser,
1498 MODEL_EFI_SKU_ID : _SkuIdParser,
1499 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
1500 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
1501 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1502 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1503 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1504 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
1505 MODEL_PCD_DYNAMIC_HII : _PcdParser,
1506 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
1507 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
1508 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
1509 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
1510 MODEL_META_DATA_COMPONENT : _ComponentParser,
1511 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,
1512 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1513 MODEL_UNKNOWN : MetaFileParser._Skip,
1514 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1515 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1516 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1517 }
1518
1519 _Macros = property(_GetMacros)
1520
1521 ## DEC file parser class
1522 #
1523 # @param FilePath The path of platform description file
1524 # @param FileType The raw data of DSC file
1525 # @param Table Database used to retrieve module/package information
1526 # @param Macros Macros used for replacement in file
1527 #
1528 class DecParser(MetaFileParser):
1529 # DEC file supported data types (one type per section)
1530 DataType = {
1531 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1532 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1533 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1534 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1535 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1536 TAB_PPIS.upper() : MODEL_EFI_PPI,
1537 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1538 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1539 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1540 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1541 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1542 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1543 }
1544
1545 ## Constructor of DecParser
1546 #
1547 # Initialize object of DecParser
1548 #
1549 # @param FilePath The path of platform description file
1550 # @param FileType The raw data of DSC file
1551 # @param Table Database used to retrieve module/package information
1552 # @param Macros Macros used for replacement in file
1553 #
1554 def __init__(self, FilePath, FileType, Table):
1555 # prevent re-initialization
1556 if hasattr(self, "_Table"):
1557 return
1558 MetaFileParser.__init__(self, FilePath, FileType, Table, -1)
1559 self._Comments = []
1560 self._Version = 0x00010005 # Only EDK2 dec file is supported
1561 self._AllPCDs = [] # Only for check duplicate PCD
1562
1563 ## Parser starter
1564 def Start(self):
1565 Content = ''
1566 try:
1567 Content = open(str(self.MetaFile), 'r').readlines()
1568 except:
1569 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1570
1571 for Index in range(0, len(Content)):
1572 Line, Comment = CleanString2(Content[Index])
1573 self._CurrentLine = Line
1574 self._LineIndex = Index
1575
1576 # save comment for later use
1577 if Comment:
1578 self._Comments.append((Comment, self._LineIndex + 1))
1579 # skip empty line
1580 if Line == '':
1581 continue
1582
1583 # section header
1584 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
1585 self._SectionHeaderParser()
1586 self._Comments = []
1587 continue
1588 elif len(self._SectionType) == 0:
1589 self._Comments = []
1590 continue
1591
1592 # section content
1593 self._ValueList = ['', '', '']
1594 self._SectionParser[self._SectionType[0]](self)
1595 if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
1596 self._ItemType = -1
1597 self._Comments = []
1598 continue
1599
1600 #
1601 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1602 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1603 #
1604 for Arch, ModuleType, Type in self._Scope:
1605 self._LastItem = self._Store(
1606 Type,
1607 self._ValueList[0],
1608 self._ValueList[1],
1609 self._ValueList[2],
1610 Arch,
1611 ModuleType,
1612 self._Owner[-1],
1613 self._LineIndex + 1,
1614 - 1,
1615 self._LineIndex + 1,
1616 - 1,
1617 0
1618 )
1619 for Comment, LineNo in self._Comments:
1620 self._Store(
1621 MODEL_META_DATA_COMMENT,
1622 Comment,
1623 self._ValueList[0],
1624 self._ValueList[1],
1625 Arch,
1626 ModuleType,
1627 self._LastItem,
1628 LineNo,
1629 - 1,
1630 LineNo,
1631 - 1,
1632 0
1633 )
1634 self._Comments = []
1635 self._Done()
1636
1637
1638 ## Section header parser
1639 #
1640 # The section header is always in following format:
1641 #
1642 # [section_name.arch<.platform|module_type>]
1643 #
1644 def _SectionHeaderParser(self):
1645 self._Scope = []
1646 self._SectionName = ''
1647 self._SectionType = []
1648 ArchList = set()
1649 Line = self._CurrentLine.replace("%s%s" % (TAB_COMMA_SPLIT, TAB_SPACE_SPLIT), TAB_COMMA_SPLIT)
1650 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
1651 if Item == '':
1652 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
1653 "section name can NOT be empty or incorrectly use separator comma",
1654 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1655 ItemList = Item.split(TAB_SPLIT)
1656
1657 # different types of PCD are permissible in one section
1658 self._SectionName = ItemList[0].upper()
1659 if self._SectionName in self.DataType:
1660 if self.DataType[self._SectionName] not in self._SectionType:
1661 self._SectionType.append(self.DataType[self._SectionName])
1662 else:
1663 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
1664 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1665
1666 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1667 EdkLogger.error(
1668 'Parser',
1669 FORMAT_INVALID,
1670 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1671 File=self.MetaFile,
1672 Line=self._LineIndex + 1,
1673 ExtraData=self._CurrentLine
1674 )
1675 # S1 is always Arch
1676 if len(ItemList) > 1:
1677 S1 = ItemList[1].upper()
1678 else:
1679 S1 = 'COMMON'
1680 ArchList.add(S1)
1681 # S2 may be Platform or ModuleType
1682 if len(ItemList) > 2:
1683 S2 = ItemList[2].upper()
1684 else:
1685 S2 = 'COMMON'
1686 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1687 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1688
1689 # 'COMMON' must not be used with specific ARCHs at the same section
1690 if 'COMMON' in ArchList and len(ArchList) > 1:
1691 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1692 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1693
1694 ## [guids], [ppis] and [protocols] section parser
1695 @ParseMacro
1696 def _GuidParser(self):
1697 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1698 if len(TokenList) < 2:
1699 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1700 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1701 File=self.MetaFile, Line=self._LineIndex + 1)
1702 if TokenList[0] == '':
1703 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1704 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1705 File=self.MetaFile, Line=self._LineIndex + 1)
1706 if TokenList[1] == '':
1707 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1708 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1709 File=self.MetaFile, Line=self._LineIndex + 1)
1710 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1711 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1712 ExtraData=self._CurrentLine + \
1713 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1714 File=self.MetaFile, Line=self._LineIndex + 1)
1715 self._ValueList[0] = TokenList[0]
1716 self._ValueList[1] = TokenList[1]
1717
1718 ## PCD sections parser
1719 #
1720 # [PcdsFixedAtBuild]
1721 # [PcdsPatchableInModule]
1722 # [PcdsFeatureFlag]
1723 # [PcdsDynamicEx
1724 # [PcdsDynamic]
1725 #
1726 @ParseMacro
1727 def _PcdParser(self):
1728 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1729 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1730 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
1731 # check PCD information
1732 if self._ValueList[0] == '' or self._ValueList[1] == '':
1733 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1734 ExtraData=self._CurrentLine + \
1735 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1736 File=self.MetaFile, Line=self._LineIndex + 1)
1737 # check format of token space GUID CName
1738 if not ValueRe.match(self._ValueList[0]):
1739 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_]*'",
1740 ExtraData=self._CurrentLine + \
1741 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1742 File=self.MetaFile, Line=self._LineIndex + 1)
1743 # check format of PCD CName
1744 if not ValueRe.match(self._ValueList[1]):
1745 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1746 ExtraData=self._CurrentLine + \
1747 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1748 File=self.MetaFile, Line=self._LineIndex + 1)
1749 # check PCD datum information
1750 if len(TokenList) < 2 or TokenList[1] == '':
1751 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
1752 ExtraData=self._CurrentLine + \
1753 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1754 File=self.MetaFile, Line=self._LineIndex + 1)
1755
1756
1757 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1758 PtrValue = ValueRe.findall(TokenList[1])
1759
1760 # Has VOID* type string, may contain "|" character in the string.
1761 if len(PtrValue) != 0:
1762 ptrValueList = re.sub(ValueRe, '', TokenList[1])
1763 ValueList = GetSplitValueList(ptrValueList)
1764 ValueList[0] = PtrValue[0]
1765 else:
1766 ValueList = GetSplitValueList(TokenList[1])
1767
1768
1769 # check if there's enough datum information given
1770 if len(ValueList) != 3:
1771 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
1772 ExtraData=self._CurrentLine + \
1773 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1774 File=self.MetaFile, Line=self._LineIndex + 1)
1775 # check default value
1776 if ValueList[0] == '':
1777 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
1778 ExtraData=self._CurrentLine + \
1779 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1780 File=self.MetaFile, Line=self._LineIndex + 1)
1781 # check datum type
1782 if ValueList[1] == '':
1783 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
1784 ExtraData=self._CurrentLine + \
1785 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1786 File=self.MetaFile, Line=self._LineIndex + 1)
1787 # check token of the PCD
1788 if ValueList[2] == '':
1789 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
1790 ExtraData=self._CurrentLine + \
1791 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1792 File=self.MetaFile, Line=self._LineIndex + 1)
1793 # check format of default value against the datum type
1794 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
1795 if not IsValid:
1796 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
1797 File=self.MetaFile, Line=self._LineIndex + 1)
1798
1799 if ValueList[0] in ['True', 'true', 'TRUE']:
1800 ValueList[0] = '1'
1801 elif ValueList[0] in ['False', 'false', 'FALSE']:
1802 ValueList[0] = '0'
1803
1804 # check for duplicate PCD definition
1805 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
1806 EdkLogger.error('Parser', FORMAT_INVALID,
1807 "The same PCD name and GUID have been already defined",
1808 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1809 else:
1810 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
1811
1812 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
1813
1814 _SectionParser = {
1815 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
1816 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
1817 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
1818 MODEL_EFI_GUID : _GuidParser,
1819 MODEL_EFI_PPI : _GuidParser,
1820 MODEL_EFI_PROTOCOL : _GuidParser,
1821 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1822 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1823 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1824 MODEL_PCD_DYNAMIC : _PcdParser,
1825 MODEL_PCD_DYNAMIC_EX : _PcdParser,
1826 MODEL_UNKNOWN : MetaFileParser._Skip,
1827 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1828 }
1829
1830 ##
1831 #
1832 # This acts like the main() function for the script, unless it is 'import'ed into another
1833 # script.
1834 #
1835 if __name__ == '__main__':
1836 pass
1837