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