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