]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/MetaFileParser.py
Sync BaseTool trunk (version r2610) 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) > 3:
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 GetHeaderComment = False
499 Comments = []
500
501 for Index in range(0, len(Content)):
502 # skip empty, commented, block commented lines
503 Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)
504 NextLine = ''
505 if Index + 1 < len(Content):
506 NextLine, NextComment = CleanString2(Content[Index + 1])
507 if Line == '':
508 if Comment:
509 Comments.append((Comment, Index + 1))
510 continue
511 if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:
512 IsFindBlockComment = True
513 continue
514 if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:
515 IsFindBlockComment = False
516 continue
517 if IsFindBlockComment:
518 continue
519
520 self._LineIndex = Index
521 self._CurrentLine = Line
522
523 # section header
524 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
525 if not GetHeaderComment:
526 for Cmt, LNo in Comments:
527 self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', 'COMMON',
528 'COMMON', self._Owner[-1], LNo, -1, LNo, -1, 0)
529 GetHeaderComment = True
530 Comments = []
531 self._SectionHeaderParser()
532 # Check invalid sections
533 if self._Version < 0x00010005:
534 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
535 MODEL_EFI_LIBRARY_CLASS,
536 MODEL_META_DATA_PACKAGE,
537 MODEL_PCD_FIXED_AT_BUILD,
538 MODEL_PCD_PATCHABLE_IN_MODULE,
539 MODEL_PCD_FEATURE_FLAG,
540 MODEL_PCD_DYNAMIC_EX,
541 MODEL_PCD_DYNAMIC,
542 MODEL_EFI_GUID,
543 MODEL_EFI_PROTOCOL,
544 MODEL_EFI_PPI,
545 MODEL_META_DATA_USER_EXTENSION]:
546 EdkLogger.error('Parser', FORMAT_INVALID,
547 "Section [%s] is not allowed in inf file without version" % (self._SectionName),
548 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
549 elif self._SectionType in [MODEL_EFI_INCLUDE,
550 MODEL_EFI_LIBRARY_INSTANCE,
551 MODEL_META_DATA_NMAKE]:
552 EdkLogger.error('Parser', FORMAT_INVALID,
553 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
554 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
555 continue
556 # merge two lines specified by '\' in section NMAKE
557 elif self._SectionType == MODEL_META_DATA_NMAKE:
558 if Line[-1] == '\\':
559 if NextLine == '':
560 self._CurrentLine = NmakeLine + Line[0:-1]
561 NmakeLine = ''
562 else:
563 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
564 self._CurrentLine = NmakeLine + Line[0:-1]
565 NmakeLine = ''
566 else:
567 NmakeLine = NmakeLine + ' ' + Line[0:-1]
568 continue
569 else:
570 self._CurrentLine = NmakeLine + Line
571 NmakeLine = ''
572
573 # section content
574 self._ValueList = ['', '', '']
575 # parse current line, result will be put in self._ValueList
576 self._SectionParser[self._SectionType](self)
577 if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
578 self._ItemType = -1
579 Comments = []
580 continue
581 if Comment:
582 Comments.append((Comment, Index + 1))
583 #
584 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
585 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
586 #
587 for Arch, Platform in self._Scope:
588 LastItem = self._Store(self._SectionType,
589 self._ValueList[0],
590 self._ValueList[1],
591 self._ValueList[2],
592 Arch,
593 Platform,
594 self._Owner[-1],
595 self._LineIndex + 1,
596 - 1,
597 self._LineIndex + 1,
598 - 1,
599 0
600 )
601 for Comment, LineNo in Comments:
602 self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,
603 LastItem, LineNo, -1, LineNo, -1, 0)
604 Comments = []
605 if IsFindBlockComment:
606 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
607 File=self.MetaFile)
608 self._Done()
609
610 ## Data parser for the format in which there's path
611 #
612 # Only path can have macro used. So we need to replace them before use.
613 #
614 def _IncludeParser(self):
615 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
616 self._ValueList[0:len(TokenList)] = TokenList
617 Macros = self._Macros
618 if Macros:
619 for Index in range(0, len(self._ValueList)):
620 Value = self._ValueList[Index]
621 if not Value:
622 continue
623
624 if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
625 Value = '$(EDK_SOURCE)' + Value[17:]
626 if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:
627 pass
628 elif Value.startswith('.'):
629 pass
630 elif Value.startswith('$('):
631 pass
632 else:
633 Value = '$(EFI_SOURCE)/' + Value
634
635 self._ValueList[Index] = ReplaceMacro(Value, Macros)
636
637 ## Parse [Sources] section
638 #
639 # Only path can have macro used. So we need to replace them before use.
640 #
641 @ParseMacro
642 def _SourceFileParser(self):
643 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
644 self._ValueList[0:len(TokenList)] = TokenList
645 Macros = self._Macros
646 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
647 if 'COMPONENT_TYPE' in Macros:
648 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
649 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
650 if self._Defines['BASE_NAME'] == 'Microcode':
651 pass
652 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
653
654 ## Parse [Binaries] section
655 #
656 # Only path can have macro used. So we need to replace them before use.
657 #
658 @ParseMacro
659 def _BinaryFileParser(self):
660 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
661 if len(TokenList) < 2:
662 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
663 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
664 File=self.MetaFile, Line=self._LineIndex + 1)
665 if not TokenList[0]:
666 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
667 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
668 File=self.MetaFile, Line=self._LineIndex + 1)
669 if not TokenList[1]:
670 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
671 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
672 File=self.MetaFile, Line=self._LineIndex + 1)
673 self._ValueList[0:len(TokenList)] = TokenList
674 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
675
676 ## [nmake] section parser (Edk.x style only)
677 def _NmakeParser(self):
678 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
679 self._ValueList[0:len(TokenList)] = TokenList
680 # remove macros
681 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
682 # remove self-reference in macro setting
683 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
684
685 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
686 @ParseMacro
687 def _PcdParser(self):
688 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
689 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
690 if len(ValueList) != 2:
691 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
692 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
693 File=self.MetaFile, Line=self._LineIndex + 1)
694 self._ValueList[0:1] = ValueList
695 if len(TokenList) > 1:
696 self._ValueList[2] = TokenList[1]
697 if self._ValueList[0] == '' or self._ValueList[1] == '':
698 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
699 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
700 File=self.MetaFile, Line=self._LineIndex + 1)
701
702 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
703 if self._ValueList[2] != '':
704 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
705 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
706 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
707 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
708 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
709 if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:
710 self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType
711 elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:
712 EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",
713 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
714 File=self.MetaFile, Line=self._LineIndex + 1)
715
716 ## [depex] section parser
717 @ParseMacro
718 def _DepexParser(self):
719 self._ValueList[0:1] = [self._CurrentLine]
720
721 _SectionParser = {
722 MODEL_UNKNOWN : MetaFileParser._Skip,
723 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
724 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
725 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules
726 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules
727 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
728 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
729 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules
730 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
731 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
732 MODEL_PCD_FEATURE_FLAG : _PcdParser,
733 MODEL_PCD_DYNAMIC_EX : _PcdParser,
734 MODEL_PCD_DYNAMIC : _PcdParser,
735 MODEL_EFI_SOURCE_FILE : _SourceFileParser,
736 MODEL_EFI_GUID : MetaFileParser._CommonParser,
737 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
738 MODEL_EFI_PPI : MetaFileParser._CommonParser,
739 MODEL_EFI_DEPEX : _DepexParser,
740 MODEL_EFI_BINARY_FILE : _BinaryFileParser,
741 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
742 }
743
744 ## DSC file parser class
745 #
746 # @param FilePath The path of platform description file
747 # @param FileType The raw data of DSC file
748 # @param Table Database used to retrieve module/package information
749 # @param Macros Macros used for replacement in file
750 # @param Owner Owner ID (for sub-section parsing)
751 # @param From ID from which the data comes (for !INCLUDE directive)
752 #
753 class DscParser(MetaFileParser):
754 # DSC file supported data types (one type per section)
755 DataType = {
756 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
757 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
758 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
759 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
760 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
761 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
762 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
763 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
764 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
765 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
766 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
767 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
768 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
769 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
770 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
771 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,
772 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
773 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,
774 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,
775 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
776 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
777 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
778 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
779 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
780 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
781 }
782
783 # Valid names in define section
784 DefineKeywords = [
785 "DSC_SPECIFICATION",
786 "PLATFORM_NAME",
787 "PLATFORM_GUID",
788 "PLATFORM_VERSION",
789 "SKUID_IDENTIFIER",
790 "PCD_INFO_GENERATION",
791 "SUPPORTED_ARCHITECTURES",
792 "BUILD_TARGETS",
793 "OUTPUT_DIRECTORY",
794 "FLASH_DEFINITION",
795 "BUILD_NUMBER",
796 "RFC_LANGUAGES",
797 "ISO_LANGUAGES",
798 "TIME_STAMP_FILE",
799 "VPD_TOOL_GUID",
800 "FIX_LOAD_TOP_MEMORY_ADDRESS"
801 ]
802
803 SymbolPattern = ValueExpression.SymbolPattern
804
805 ## Constructor of DscParser
806 #
807 # Initialize object of DscParser
808 #
809 # @param FilePath The path of platform description file
810 # @param FileType The raw data of DSC file
811 # @param Table Database used to retrieve module/package information
812 # @param Macros Macros used for replacement in file
813 # @param Owner Owner ID (for sub-section parsing)
814 # @param From ID from which the data comes (for !INCLUDE directive)
815 #
816 def __init__(self, FilePath, FileType, Table, Owner= -1, From= -1):
817 # prevent re-initialization
818 if hasattr(self, "_Table"):
819 return
820 MetaFileParser.__init__(self, FilePath, FileType, Table, Owner, From)
821 self._Version = 0x00010005 # Only EDK2 dsc file is supported
822 # to store conditional directive evaluation result
823 self._DirectiveStack = []
824 self._DirectiveEvalStack = []
825 self._Enabled = 1
826
827 #
828 # Specify whether current line is in uncertain condition
829 #
830 self._InDirective = -1
831
832 # Final valid replacable symbols
833 self._Symbols = {}
834 #
835 # Map the ID between the original table and new table to track
836 # the owner item
837 #
838 self._IdMapping = {-1:-1}
839
840 ## Parser starter
841 def Start(self):
842 Content = ''
843 try:
844 Content = open(str(self.MetaFile), 'r').readlines()
845 except:
846 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
847
848 OwnerId = {}
849 for Index in range(0, len(Content)):
850 Line = CleanString(Content[Index])
851 # skip empty line
852 if Line == '':
853 continue
854
855 self._CurrentLine = Line
856 self._LineIndex = Index
857 if self._InSubsection and self._Owner[-1] == -1:
858 self._Owner.append(self._LastItem)
859
860 # section header
861 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
862 self._SectionType = MODEL_META_DATA_SECTION_HEADER
863 # subsection ending
864 elif Line[0] == '}' and self._InSubsection:
865 self._InSubsection = False
866 self._SubsectionType = MODEL_UNKNOWN
867 self._SubsectionName = ''
868 self._Owner[-1] = -1
869 OwnerId = {}
870 continue
871 # subsection header
872 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
873 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
874 # directive line
875 elif Line[0] == '!':
876 self._DirectiveParser()
877 continue
878
879 if self._InSubsection:
880 SectionType = self._SubsectionType
881 else:
882 SectionType = self._SectionType
883 self._ItemType = SectionType
884
885 self._ValueList = ['', '', '']
886 self._SectionParser[SectionType](self)
887 if self._ValueList == None:
888 continue
889 #
890 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
891 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
892 #
893 for Arch, ModuleType in self._Scope:
894 Owner = self._Owner[-1]
895 if self._SubsectionType != MODEL_UNKNOWN:
896 Owner = OwnerId[Arch]
897 self._LastItem = self._Store(
898 self._ItemType,
899 self._ValueList[0],
900 self._ValueList[1],
901 self._ValueList[2],
902 Arch,
903 ModuleType,
904 Owner,
905 self._From,
906 self._LineIndex + 1,
907 - 1,
908 self._LineIndex + 1,
909 - 1,
910 self._Enabled
911 )
912 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
913 OwnerId[Arch] = self._LastItem
914
915 if self._DirectiveStack:
916 Type, Line, Text = self._DirectiveStack[-1]
917 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
918 ExtraData=Text, File=self.MetaFile, Line=Line)
919 self._Done()
920
921 ## <subsection_header> parser
922 def _SubsectionHeaderParser(self):
923 self._SubsectionName = self._CurrentLine[1:-1].upper()
924 if self._SubsectionName in self.DataType:
925 self._SubsectionType = self.DataType[self._SubsectionName]
926 else:
927 self._SubsectionType = MODEL_UNKNOWN
928 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
929 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
930 self._ValueList[0] = self._SubsectionName
931
932 ## Directive statement parser
933 def _DirectiveParser(self):
934 self._ValueList = ['', '', '']
935 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
936 self._ValueList[0:len(TokenList)] = TokenList
937
938 # Syntax check
939 DirectiveName = self._ValueList[0].upper()
940 if DirectiveName not in self.DataType:
941 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
942 File=self.MetaFile, Line=self._LineIndex + 1)
943
944 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
945 self._InDirective += 1
946
947 if DirectiveName in ['!ENDIF']:
948 self._InDirective -= 1
949
950 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
951 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
952 File=self.MetaFile, Line=self._LineIndex + 1,
953 ExtraData=self._CurrentLine)
954
955 ItemType = self.DataType[DirectiveName]
956 Scope = [['COMMON', 'COMMON']]
957 if ItemType == MODEL_META_DATA_INCLUDE:
958 Scope = self._Scope
959 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
960 # Remove all directives between !if and !endif, including themselves
961 while self._DirectiveStack:
962 # Remove any !else or !elseif
963 DirectiveInfo = self._DirectiveStack.pop()
964 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
965 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
966 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
967 break
968 else:
969 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
970 File=self.MetaFile, Line=self._LineIndex + 1,
971 ExtraData=self._CurrentLine)
972 elif ItemType != MODEL_META_DATA_INCLUDE:
973 # Break if there's a !else is followed by a !elseif
974 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
975 self._DirectiveStack and \
976 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
977 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
978 File=self.MetaFile, Line=self._LineIndex + 1,
979 ExtraData=self._CurrentLine)
980 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
981 elif self._From > 0:
982 EdkLogger.error('Parser', FORMAT_INVALID,
983 "No '!include' allowed in included file",
984 ExtraData=self._CurrentLine, File=self.MetaFile,
985 Line=self._LineIndex + 1)
986
987 #
988 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
989 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
990 #
991 for Arch, ModuleType in Scope:
992 self._LastItem = self._Store(
993 ItemType,
994 self._ValueList[0],
995 self._ValueList[1],
996 self._ValueList[2],
997 Arch,
998 ModuleType,
999 self._Owner[-1],
1000 self._From,
1001 self._LineIndex + 1,
1002 - 1,
1003 self._LineIndex + 1,
1004 - 1,
1005 0
1006 )
1007
1008 ## [defines] section parser
1009 @ParseMacro
1010 def _DefineParser(self):
1011 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1012 self._ValueList[1:len(TokenList)] = TokenList
1013
1014 # Syntax check
1015 if not self._ValueList[1]:
1016 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
1017 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1018 if not self._ValueList[2]:
1019 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
1020 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1021 if not self._ValueList[1] in self.DefineKeywords:
1022 EdkLogger.error('Parser', FORMAT_INVALID,
1023 "Unknown keyword found: %s. "
1024 "If this is a macro you must "
1025 "add it as a DEFINE in the DSC" % self._ValueList[1],
1026 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1027 self._Defines[self._ValueList[1]] = self._ValueList[2]
1028 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
1029
1030 @ParseMacro
1031 def _SkuIdParser(self):
1032 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1033 if len(TokenList) != 2:
1034 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",
1035 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1036 self._ValueList[0:len(TokenList)] = TokenList
1037
1038 ## Parse Edk style of library modules
1039 @ParseMacro
1040 def _LibraryInstanceParser(self):
1041 self._ValueList[0] = self._CurrentLine
1042
1043 ## PCD sections parser
1044 #
1045 # [PcdsFixedAtBuild]
1046 # [PcdsPatchableInModule]
1047 # [PcdsFeatureFlag]
1048 # [PcdsDynamicEx
1049 # [PcdsDynamicExDefault]
1050 # [PcdsDynamicExVpd]
1051 # [PcdsDynamicExHii]
1052 # [PcdsDynamic]
1053 # [PcdsDynamicDefault]
1054 # [PcdsDynamicVpd]
1055 # [PcdsDynamicHii]
1056 #
1057 @ParseMacro
1058 def _PcdParser(self):
1059 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1060 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1061 if len(TokenList) == 2:
1062 self._ValueList[2] = TokenList[1]
1063 if self._ValueList[0] == '' or self._ValueList[1] == '':
1064 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1065 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1066 File=self.MetaFile, Line=self._LineIndex + 1)
1067 if self._ValueList[2] == '':
1068 #
1069 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1070 #
1071 if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
1072 return
1073 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
1074 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1075 File=self.MetaFile, Line=self._LineIndex + 1)
1076
1077 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1078 ValueList = GetSplitValueList(self._ValueList[2])
1079 if len(ValueList) > 1 and ValueList[1] != TAB_VOID \
1080 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
1081 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
1082 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1083
1084 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1085 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1086 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
1087 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
1088 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
1089 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
1090
1091
1092 ## [components] section parser
1093 @ParseMacro
1094 def _ComponentParser(self):
1095 if self._CurrentLine[-1] == '{':
1096 self._ValueList[0] = self._CurrentLine[0:-1].strip()
1097 self._InSubsection = True
1098 else:
1099 self._ValueList[0] = self._CurrentLine
1100
1101 ## [LibraryClasses] section
1102 @ParseMacro
1103 def _LibraryClassParser(self):
1104 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1105 if len(TokenList) < 2:
1106 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
1107 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1108 File=self.MetaFile, Line=self._LineIndex + 1)
1109 if TokenList[0] == '':
1110 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
1111 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1112 File=self.MetaFile, Line=self._LineIndex + 1)
1113 if TokenList[1] == '':
1114 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
1115 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1116 File=self.MetaFile, Line=self._LineIndex + 1)
1117
1118 self._ValueList[0:len(TokenList)] = TokenList
1119
1120 def _CompponentSourceOverridePathParser(self):
1121 self._ValueList[0] = self._CurrentLine
1122
1123 ## [BuildOptions] section parser
1124 @ParseMacro
1125 def _BuildOptionParser(self):
1126 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
1127 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1128 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
1129 if len(TokenList2) == 2:
1130 self._ValueList[0] = TokenList2[0] # toolchain family
1131 self._ValueList[1] = TokenList2[1] # keys
1132 else:
1133 self._ValueList[1] = TokenList[0]
1134 if len(TokenList) == 2: # value
1135 self._ValueList[2] = TokenList[1]
1136
1137 if self._ValueList[1].count('_') != 4:
1138 EdkLogger.error(
1139 'Parser',
1140 FORMAT_INVALID,
1141 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
1142 ExtraData=self._CurrentLine,
1143 File=self.MetaFile,
1144 Line=self._LineIndex + 1
1145 )
1146
1147 ## Override parent's method since we'll do all macro replacements in parser
1148 def _GetMacros(self):
1149 Macros = {}
1150 Macros.update(self._FileLocalMacros)
1151 Macros.update(self._GetApplicableSectionMacro())
1152 Macros.update(GlobalData.gEdkGlobal)
1153 Macros.update(GlobalData.gPlatformDefines)
1154 Macros.update(GlobalData.gCommandLineDefines)
1155 # PCD cannot be referenced in macro definition
1156 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
1157 Macros.update(self._Symbols)
1158 return Macros
1159
1160 def _PostProcess(self):
1161 Processer = {
1162 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,
1163 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,
1164 MODEL_META_DATA_HEADER : self.__ProcessDefine,
1165 MODEL_META_DATA_DEFINE : self.__ProcessDefine,
1166 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,
1167 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,
1168 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,
1169 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,
1170 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,
1171 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,
1172 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,
1173 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,
1174 MODEL_EFI_SKU_ID : self.__ProcessSkuId,
1175 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,
1176 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,
1177 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,
1178 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,
1179 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,
1180 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,
1181 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,
1182 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,
1183 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,
1184 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,
1185 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,
1186 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,
1187 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,
1188 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,
1189 MODEL_UNKNOWN : self._Skip,
1190 MODEL_META_DATA_USER_EXTENSION : self._Skip,
1191 }
1192
1193 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)
1194 self._Table.Create()
1195 self._DirectiveStack = []
1196 self._DirectiveEvalStack = []
1197 self._FileWithError = self.MetaFile
1198 self._FileLocalMacros = {}
1199 self._SectionsMacroDict = {}
1200 GlobalData.gPlatformDefines = {}
1201
1202 # Get all macro and PCD which has straitforward value
1203 self.__RetrievePcdValue()
1204 self._Content = self._RawTable.GetAll()
1205 self._ContentIndex = 0
1206 while self._ContentIndex < len(self._Content) :
1207 Id, self._ItemType, V1, V2, V3, S1, S2, Owner, self._From, \
1208 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
1209
1210 if self._From < 0:
1211 self._FileWithError = self.MetaFile
1212
1213 self._ContentIndex += 1
1214
1215 self._Scope = [[S1, S2]]
1216 #
1217 # For !include directive, handle it specially,
1218 # merge arch and module type in case of duplicate items
1219 #
1220 while self._ItemType == MODEL_META_DATA_INCLUDE:
1221 if self._ContentIndex >= len(self._Content):
1222 break
1223 Record = self._Content[self._ContentIndex]
1224 if LineStart == Record[9] and LineEnd == Record[11]:
1225 if [Record[5], Record[6]] not in self._Scope:
1226 self._Scope.append([Record[5], Record[6]])
1227 self._ContentIndex += 1
1228 else:
1229 break
1230
1231 self._LineIndex = LineStart - 1
1232 self._ValueList = [V1, V2, V3]
1233
1234 try:
1235 Processer[self._ItemType]()
1236 except EvaluationException, Excpt:
1237 #
1238 # Only catch expression evaluation error here. We need to report
1239 # the precise number of line on which the error occurred
1240 #
1241 if hasattr(Excpt, 'Pcd'):
1242 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
1243 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
1244 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
1245 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1246 " of the DSC file, and it is currently defined in this section:"
1247 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
1248 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1249 Line=self._LineIndex + 1)
1250 else:
1251 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
1252 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1253 Line=self._LineIndex + 1)
1254 else:
1255 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1256 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1257 Line=self._LineIndex + 1)
1258 except MacroException, Excpt:
1259 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
1260 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1261 Line=self._LineIndex + 1)
1262
1263 if self._ValueList == None:
1264 continue
1265
1266 NewOwner = self._IdMapping.get(Owner, -1)
1267 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
1268 self._LastItem = self._Store(
1269 self._ItemType,
1270 self._ValueList[0],
1271 self._ValueList[1],
1272 self._ValueList[2],
1273 S1,
1274 S2,
1275 NewOwner,
1276 self._From,
1277 self._LineIndex + 1,
1278 - 1,
1279 self._LineIndex + 1,
1280 - 1,
1281 self._Enabled
1282 )
1283 self._IdMapping[Id] = self._LastItem
1284
1285 GlobalData.gPlatformDefines.update(self._FileLocalMacros)
1286 self._PostProcessed = True
1287 self._Content = None
1288
1289 def __ProcessSectionHeader(self):
1290 self._SectionName = self._ValueList[0]
1291 if self._SectionName in self.DataType:
1292 self._SectionType = self.DataType[self._SectionName]
1293 else:
1294 self._SectionType = MODEL_UNKNOWN
1295
1296 def __ProcessSubsectionHeader(self):
1297 self._SubsectionName = self._ValueList[0]
1298 if self._SubsectionName in self.DataType:
1299 self._SubsectionType = self.DataType[self._SubsectionName]
1300 else:
1301 self._SubsectionType = MODEL_UNKNOWN
1302
1303 def __RetrievePcdValue(self):
1304 Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem= -1.0)
1305 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
1306 Name = TokenSpaceGuid + '.' + PcdName
1307 ValList, Valid, Index = AnalyzeDscPcd(Value, MODEL_PCD_FEATURE_FLAG)
1308 self._Symbols[Name] = ValList[Index]
1309
1310 Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem= -1.0)
1311 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
1312 Name = TokenSpaceGuid + '.' + PcdName
1313 ValList, Valid, Index = AnalyzeDscPcd(Value, MODEL_PCD_FIXED_AT_BUILD)
1314 self._Symbols[Name] = ValList[Index]
1315
1316 Content = open(str(self.MetaFile), 'r').readlines()
1317 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
1318 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
1319 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
1320 MODEL_PCD_DYNAMIC_EX_VPD):
1321 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
1322 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
1323 Name = TokenSpaceGuid + '.' + PcdName
1324 if Name not in GlobalData.gPlatformOtherPcds:
1325 PcdLine = Line
1326 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
1327 Line -= 1
1328 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
1329
1330 def __ProcessDefine(self):
1331 if not self._Enabled:
1332 return
1333
1334 Type, Name, Value = self._ValueList
1335 Value = ReplaceMacro(Value, self._Macros, False)
1336 if self._ItemType == MODEL_META_DATA_DEFINE:
1337 if self._SectionType == MODEL_META_DATA_HEADER:
1338 self._FileLocalMacros[Name] = Value
1339 else:
1340 self._ConstructSectionMacroDict(Name, Value)
1341 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
1342 GlobalData.gEdkGlobal[Name] = Value
1343
1344 #
1345 # Keyword in [Defines] section can be used as Macros
1346 #
1347 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
1348 self._FileLocalMacros[Name] = Value
1349
1350 self._ValueList = [Type, Name, Value]
1351
1352 def __ProcessDirective(self):
1353 Result = None
1354 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1355 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
1356 Macros = self._Macros
1357 Macros.update(GlobalData.gGlobalDefines)
1358 try:
1359 Result = ValueExpression(self._ValueList[1], Macros)()
1360 except SymbolNotFound, Exc:
1361 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1362 Result = False
1363 except WrnExpression, Excpt:
1364 #
1365 # Catch expression evaluation warning here. We need to report
1366 # the precise number of line and return the evaluation result
1367 #
1368 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
1369 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1370 Line=self._LineIndex + 1)
1371 Result = Excpt.result
1372
1373 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1374 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1375 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1376 self._DirectiveStack.append(self._ItemType)
1377 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
1378 Result = bool(Result)
1379 else:
1380 Macro = self._ValueList[1]
1381 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
1382 Result = Macro in self._Macros
1383 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
1384 Result = not Result
1385 self._DirectiveEvalStack.append(Result)
1386 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
1387 self._DirectiveStack.append(self._ItemType)
1388 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1389 self._DirectiveEvalStack.append(bool(Result))
1390 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1391 self._DirectiveStack.append(self._ItemType)
1392 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1393 self._DirectiveEvalStack.append(True)
1394 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1395 # Back to the nearest !if/!ifdef/!ifndef
1396 while self._DirectiveStack:
1397 self._DirectiveEvalStack.pop()
1398 Directive = self._DirectiveStack.pop()
1399 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1400 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1401 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1402 break
1403 elif self._ItemType == MODEL_META_DATA_INCLUDE:
1404 # The included file must be relative to workspace or same directory as DSC file
1405 __IncludeMacros = {}
1406 #
1407 # Allow using system environment variables in path after !include
1408 #
1409 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
1410 if "ECP_SOURCE" in GlobalData.gGlobalDefines.keys():
1411 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']
1412 #
1413 # During GenFds phase call DSC parser, will go into this branch.
1414 #
1415 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines.keys():
1416 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']
1417
1418 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']
1419 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']
1420 #
1421 # Allow using MACROs comes from [Defines] section to keep compatible.
1422 #
1423 __IncludeMacros.update(self._Macros)
1424
1425 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
1426 #
1427 # First search the include file under the same directory as DSC file
1428 #
1429 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
1430 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
1431 if ErrorCode != 0:
1432 #
1433 # Also search file under the WORKSPACE directory
1434 #
1435 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
1436 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
1437 if ErrorCode != 0:
1438 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
1439 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
1440
1441 self._FileWithError = IncludedFile1
1442
1443 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False)
1444 Owner = self._Content[self._ContentIndex - 1][0]
1445 Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable,
1446 Owner=Owner, From=Owner)
1447
1448 # set the parser status with current status
1449 Parser._SectionName = self._SectionName
1450 Parser._SectionType = self._SectionType
1451 Parser._Scope = self._Scope
1452 Parser._Enabled = self._Enabled
1453 # Parse the included file
1454 Parser.Start()
1455
1456 # update current status with sub-parser's status
1457 self._SectionName = Parser._SectionName
1458 self._SectionType = Parser._SectionType
1459 self._Scope = Parser._Scope
1460 self._Enabled = Parser._Enabled
1461
1462 # Insert all records in the table for the included file into dsc file table
1463 Records = IncludedFileTable.GetAll()
1464 if Records:
1465 self._Content[self._ContentIndex:self._ContentIndex] = Records
1466 self._Content.pop(self._ContentIndex - 1)
1467 self._ValueList = None
1468 self._ContentIndex -= 1
1469
1470 def __ProcessSkuId(self):
1471 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1472 for Value in self._ValueList]
1473
1474 def __ProcessLibraryInstance(self):
1475 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
1476
1477 def __ProcessLibraryClass(self):
1478 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
1479
1480 def __ProcessPcd(self):
1481 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
1482 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
1483 return
1484
1485 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
1486 if not Valid:
1487 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex+1,
1488 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1489 PcdValue = ValList[Index]
1490 if PcdValue:
1491 try:
1492 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
1493 except WrnExpression, Value:
1494 ValList[Index] = Value.result
1495
1496 if ValList[Index] == 'True':
1497 ValList[Index] = '1'
1498 if ValList[Index] == 'False':
1499 ValList[Index] = '0'
1500
1501 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1502 self._ValueList[2] = '|'.join(ValList)
1503
1504 def __ProcessComponent(self):
1505 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1506
1507 def __ProcessSourceOverridePath(self):
1508 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1509
1510 def __ProcessBuildOption(self):
1511 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
1512 for Value in self._ValueList]
1513
1514 _SectionParser = {
1515 MODEL_META_DATA_HEADER : _DefineParser,
1516 MODEL_EFI_SKU_ID : _SkuIdParser,
1517 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
1518 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
1519 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1520 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1521 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1522 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
1523 MODEL_PCD_DYNAMIC_HII : _PcdParser,
1524 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
1525 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
1526 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
1527 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
1528 MODEL_META_DATA_COMPONENT : _ComponentParser,
1529 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,
1530 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1531 MODEL_UNKNOWN : MetaFileParser._Skip,
1532 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1533 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1534 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1535 }
1536
1537 _Macros = property(_GetMacros)
1538
1539 ## DEC file parser class
1540 #
1541 # @param FilePath The path of platform description file
1542 # @param FileType The raw data of DSC file
1543 # @param Table Database used to retrieve module/package information
1544 # @param Macros Macros used for replacement in file
1545 #
1546 class DecParser(MetaFileParser):
1547 # DEC file supported data types (one type per section)
1548 DataType = {
1549 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1550 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1551 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1552 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1553 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1554 TAB_PPIS.upper() : MODEL_EFI_PPI,
1555 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1556 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1557 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1558 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1559 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1560 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1561 }
1562
1563 ## Constructor of DecParser
1564 #
1565 # Initialize object of DecParser
1566 #
1567 # @param FilePath The path of platform description file
1568 # @param FileType The raw data of DSC file
1569 # @param Table Database used to retrieve module/package information
1570 # @param Macros Macros used for replacement in file
1571 #
1572 def __init__(self, FilePath, FileType, Table):
1573 # prevent re-initialization
1574 if hasattr(self, "_Table"):
1575 return
1576 MetaFileParser.__init__(self, FilePath, FileType, Table, -1)
1577 self._Comments = []
1578 self._Version = 0x00010005 # Only EDK2 dec file is supported
1579 self._AllPCDs = [] # Only for check duplicate PCD
1580
1581 ## Parser starter
1582 def Start(self):
1583 Content = ''
1584 try:
1585 Content = open(str(self.MetaFile), 'r').readlines()
1586 except:
1587 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1588
1589 for Index in range(0, len(Content)):
1590 Line, Comment = CleanString2(Content[Index])
1591 self._CurrentLine = Line
1592 self._LineIndex = Index
1593
1594 # save comment for later use
1595 if Comment:
1596 self._Comments.append((Comment, self._LineIndex + 1))
1597 # skip empty line
1598 if Line == '':
1599 continue
1600
1601 # section header
1602 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
1603 self._SectionHeaderParser()
1604 self._Comments = []
1605 continue
1606 elif len(self._SectionType) == 0:
1607 self._Comments = []
1608 continue
1609
1610 # section content
1611 self._ValueList = ['', '', '']
1612 self._SectionParser[self._SectionType[0]](self)
1613 if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
1614 self._ItemType = -1
1615 self._Comments = []
1616 continue
1617
1618 #
1619 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1620 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1621 #
1622 for Arch, ModuleType, Type in self._Scope:
1623 self._LastItem = self._Store(
1624 Type,
1625 self._ValueList[0],
1626 self._ValueList[1],
1627 self._ValueList[2],
1628 Arch,
1629 ModuleType,
1630 self._Owner[-1],
1631 self._LineIndex + 1,
1632 - 1,
1633 self._LineIndex + 1,
1634 - 1,
1635 0
1636 )
1637 for Comment, LineNo in self._Comments:
1638 self._Store(
1639 MODEL_META_DATA_COMMENT,
1640 Comment,
1641 self._ValueList[0],
1642 self._ValueList[1],
1643 Arch,
1644 ModuleType,
1645 self._LastItem,
1646 LineNo,
1647 - 1,
1648 LineNo,
1649 - 1,
1650 0
1651 )
1652 self._Comments = []
1653 self._Done()
1654
1655
1656 ## Section header parser
1657 #
1658 # The section header is always in following format:
1659 #
1660 # [section_name.arch<.platform|module_type>]
1661 #
1662 def _SectionHeaderParser(self):
1663 self._Scope = []
1664 self._SectionName = ''
1665 self._SectionType = []
1666 ArchList = set()
1667 Line = self._CurrentLine.replace("%s%s" % (TAB_COMMA_SPLIT, TAB_SPACE_SPLIT), TAB_COMMA_SPLIT)
1668 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
1669 if Item == '':
1670 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
1671 "section name can NOT be empty or incorrectly use separator comma",
1672 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1673 ItemList = Item.split(TAB_SPLIT)
1674
1675 # different types of PCD are permissible in one section
1676 self._SectionName = ItemList[0].upper()
1677 if self._SectionName in self.DataType:
1678 if self.DataType[self._SectionName] not in self._SectionType:
1679 self._SectionType.append(self.DataType[self._SectionName])
1680 else:
1681 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
1682 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1683
1684 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1685 EdkLogger.error(
1686 'Parser',
1687 FORMAT_INVALID,
1688 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1689 File=self.MetaFile,
1690 Line=self._LineIndex + 1,
1691 ExtraData=self._CurrentLine
1692 )
1693 # S1 is always Arch
1694 if len(ItemList) > 1:
1695 S1 = ItemList[1].upper()
1696 else:
1697 S1 = 'COMMON'
1698 ArchList.add(S1)
1699 # S2 may be Platform or ModuleType
1700 if len(ItemList) > 2:
1701 S2 = ItemList[2].upper()
1702 else:
1703 S2 = 'COMMON'
1704 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1705 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1706
1707 # 'COMMON' must not be used with specific ARCHs at the same section
1708 if 'COMMON' in ArchList and len(ArchList) > 1:
1709 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1710 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1711
1712 ## [guids], [ppis] and [protocols] section parser
1713 @ParseMacro
1714 def _GuidParser(self):
1715 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1716 if len(TokenList) < 2:
1717 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1718 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1719 File=self.MetaFile, Line=self._LineIndex + 1)
1720 if TokenList[0] == '':
1721 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1722 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1723 File=self.MetaFile, Line=self._LineIndex + 1)
1724 if TokenList[1] == '':
1725 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1726 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1727 File=self.MetaFile, Line=self._LineIndex + 1)
1728 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1729 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1730 ExtraData=self._CurrentLine + \
1731 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1732 File=self.MetaFile, Line=self._LineIndex + 1)
1733 self._ValueList[0] = TokenList[0]
1734 self._ValueList[1] = TokenList[1]
1735
1736 ## PCD sections parser
1737 #
1738 # [PcdsFixedAtBuild]
1739 # [PcdsPatchableInModule]
1740 # [PcdsFeatureFlag]
1741 # [PcdsDynamicEx
1742 # [PcdsDynamic]
1743 #
1744 @ParseMacro
1745 def _PcdParser(self):
1746 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1747 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1748 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
1749 # check PCD information
1750 if self._ValueList[0] == '' or self._ValueList[1] == '':
1751 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1752 ExtraData=self._CurrentLine + \
1753 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1754 File=self.MetaFile, Line=self._LineIndex + 1)
1755 # check format of token space GUID CName
1756 if not ValueRe.match(self._ValueList[0]):
1757 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_]*'",
1758 ExtraData=self._CurrentLine + \
1759 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1760 File=self.MetaFile, Line=self._LineIndex + 1)
1761 # check format of PCD CName
1762 if not ValueRe.match(self._ValueList[1]):
1763 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1764 ExtraData=self._CurrentLine + \
1765 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1766 File=self.MetaFile, Line=self._LineIndex + 1)
1767 # check PCD datum information
1768 if len(TokenList) < 2 or TokenList[1] == '':
1769 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
1770 ExtraData=self._CurrentLine + \
1771 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1772 File=self.MetaFile, Line=self._LineIndex + 1)
1773
1774
1775 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1776 PtrValue = ValueRe.findall(TokenList[1])
1777
1778 # Has VOID* type string, may contain "|" character in the string.
1779 if len(PtrValue) != 0:
1780 ptrValueList = re.sub(ValueRe, '', TokenList[1])
1781 ValueList = GetSplitValueList(ptrValueList)
1782 ValueList[0] = PtrValue[0]
1783 else:
1784 ValueList = GetSplitValueList(TokenList[1])
1785
1786
1787 # check if there's enough datum information given
1788 if len(ValueList) != 3:
1789 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
1790 ExtraData=self._CurrentLine + \
1791 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1792 File=self.MetaFile, Line=self._LineIndex + 1)
1793 # check default value
1794 if ValueList[0] == '':
1795 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
1796 ExtraData=self._CurrentLine + \
1797 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1798 File=self.MetaFile, Line=self._LineIndex + 1)
1799 # check datum type
1800 if ValueList[1] == '':
1801 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
1802 ExtraData=self._CurrentLine + \
1803 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1804 File=self.MetaFile, Line=self._LineIndex + 1)
1805 # check token of the PCD
1806 if ValueList[2] == '':
1807 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
1808 ExtraData=self._CurrentLine + \
1809 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1810 File=self.MetaFile, Line=self._LineIndex + 1)
1811 # check format of default value against the datum type
1812 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
1813 if not IsValid:
1814 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
1815 File=self.MetaFile, Line=self._LineIndex + 1)
1816
1817 if ValueList[0] in ['True', 'true', 'TRUE']:
1818 ValueList[0] = '1'
1819 elif ValueList[0] in ['False', 'false', 'FALSE']:
1820 ValueList[0] = '0'
1821
1822 # check for duplicate PCD definition
1823 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
1824 EdkLogger.error('Parser', FORMAT_INVALID,
1825 "The same PCD name and GUID have been already defined",
1826 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1827 else:
1828 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
1829
1830 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
1831
1832 _SectionParser = {
1833 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
1834 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
1835 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
1836 MODEL_EFI_GUID : _GuidParser,
1837 MODEL_EFI_PPI : _GuidParser,
1838 MODEL_EFI_PROTOCOL : _GuidParser,
1839 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1840 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1841 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1842 MODEL_PCD_DYNAMIC : _PcdParser,
1843 MODEL_PCD_DYNAMIC_EX : _PcdParser,
1844 MODEL_UNKNOWN : MetaFileParser._Skip,
1845 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1846 }
1847
1848 ##
1849 #
1850 # This acts like the main() function for the script, unless it is 'import'ed into another
1851 # script.
1852 #
1853 if __name__ == '__main__':
1854 pass
1855