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