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