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