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