]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Workspace/MetaFileParser.py
Sync basetools' source and binary files with r1707 of the basetools project.
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileParser.py
CommitLineData
30fdf114
LG
1## @file
2# This file is used to parse meta files
3#
4# Copyright (c) 2008, Intel Corporation
5# All rights reserved. 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#
17import os
18import time
fd171542 19import copy
30fdf114
LG
20
21import Common.EdkLogger as EdkLogger
22from CommonDataClass.DataClass import *
23from Common.DataType import *
24from Common.String import *
25from Common.Misc import Blist, GuidStructureStringToGuidString, CheckPcdDatum
26
27## Base class of parser
28#
29# This class is used for derivation purpose. The specific parser for one kind
30# type file must derive this class and implement some public interfaces.
31#
32# @param FilePath The path of platform description file
33# @param FileType The raw data of DSC file
34# @param Table Database used to retrieve module/package information
35# @param Macros Macros used for replacement in file
36# @param Owner Owner ID (for sub-section parsing)
37# @param From ID from which the data comes (for !INCLUDE directive)
38#
39class MetaFileParser(object):
40 # data type (file content) for specific file type
41 DataType = {}
42
43 ## Constructor of MetaFileParser
44 #
45 # Initialize object of MetaFileParser
46 #
47 # @param FilePath The path of platform description file
48 # @param FileType The raw data of DSC file
49 # @param Table Database used to retrieve module/package information
50 # @param Macros Macros used for replacement in file
51 # @param Owner Owner ID (for sub-section parsing)
52 # @param From ID from which the data comes (for !INCLUDE directive)
53 #
54 def __init__(self, FilePath, FileType, Table, Macros=None, Owner=-1, From=-1):
55 self._Table = Table
56 self._FileType = FileType
57 self.MetaFile = FilePath
58 self._FileDir = os.path.dirname(self.MetaFile)
fd171542 59 self._Macros = copy.copy(Macros)
30fdf114
LG
60
61 # for recursive parsing
62 self._Owner = Owner
63 self._From = From
64
65 # parsr status for parsing
66 self._Content = None
67 self._ValueList = ['', '', '', '', '']
68 self._Scope = []
69 self._LineIndex = 0
70 self._CurrentLine = ''
71 self._SectionType = MODEL_UNKNOWN
72 self._SectionName = ''
73 self._InSubsection = False
74 self._SubsectionType = MODEL_UNKNOWN
75 self._SubsectionName = ''
76 self._LastItem = -1
77 self._Enabled = 0
78 self._Finished = False
79
80 ## Store the parsed data in table
81 def _Store(self, *Args):
82 return self._Table.Insert(*Args)
83
84 ## Virtual method for starting parse
85 def Start(self):
86 raise NotImplementedError
87
88 ## Set parsing complete flag in both class and table
89 def _Done(self):
90 self._Finished = True
fd171542 91 ## Do not set end flag when processing included files
92 if self._From == -1:
93 self._Table.SetEndFlag()
30fdf114
LG
94
95 ## Return the table containg parsed data
96 #
97 # If the parse complete flag is not set, this method will try to parse the
98 # file before return the table
99 #
100 def _GetTable(self):
101 if not self._Finished:
102 self.Start()
103 return self._Table
104
105 ## Get the parse complete flag
106 def _GetFinished(self):
107 return self._Finished
108
109 ## Set the complete flag
110 def _SetFinished(self, Value):
111 self._Finished = Value
112
113 ## Use [] style to query data in table, just for readability
114 #
115 # DataInfo = [data_type, scope1(arch), scope2(platform,moduletype)]
116 #
117 def __getitem__(self, DataInfo):
118 if type(DataInfo) != type(()):
119 DataInfo = (DataInfo,)
120 return self.Table.Query(*DataInfo)
121
122 ## Data parser for the common format in different type of file
123 #
124 # The common format in the meatfile is like
125 #
126 # xxx1 | xxx2 | xxx3
127 #
128 def _CommonParser(self):
129 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
130 self._ValueList[0:len(TokenList)] = TokenList
131
132 ## Data parser for the format in which there's path
133 #
134 # Only path can have macro used. So we need to replace them before use.
135 #
136 def _PathParser(self):
137 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
138 self._ValueList[0:len(TokenList)] = TokenList
139 if len(self._Macros) > 0:
140 for Index in range(0, len(self._ValueList)):
141 Value = self._ValueList[Index]
142 if Value == None or Value == '':
143 continue
144 self._ValueList[Index] = NormPath(Value, self._Macros)
145
146 ## Skip unsupported data
147 def _Skip(self):
148 EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
149 Line=self._LineIndex+1, ExtraData=self._CurrentLine);
150 self._ValueList[0:1] = [self._CurrentLine]
151
152 ## Section header parser
153 #
154 # The section header is always in following format:
155 #
156 # [section_name.arch<.platform|module_type>]
157 #
158 def _SectionHeaderParser(self):
159 self._Scope = []
160 self._SectionName = ''
161 ArchList = set()
162 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
163 if Item == '':
164 continue
165 ItemList = GetSplitValueList(Item, TAB_SPLIT)
166 # different section should not mix in one section
167 if self._SectionName != '' and self._SectionName != ItemList[0].upper():
168 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
169 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
170 self._SectionName = ItemList[0].upper()
171 if self._SectionName in self.DataType:
172 self._SectionType = self.DataType[self._SectionName]
173 else:
174 self._SectionType = MODEL_UNKNOWN
175 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
176 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
177 # S1 is always Arch
178 if len(ItemList) > 1:
179 S1 = ItemList[1].upper()
180 else:
181 S1 = 'COMMON'
182 ArchList.add(S1)
183 # S2 may be Platform or ModuleType
184 if len(ItemList) > 2:
185 S2 = ItemList[2].upper()
186 else:
187 S2 = 'COMMON'
188 self._Scope.append([S1, S2])
189
190 # 'COMMON' must not be used with specific ARCHs at the same section
191 if 'COMMON' in ArchList and len(ArchList) > 1:
192 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
193 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
194
195 ## [defines] section parser
196 def _DefineParser(self):
197 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
198 self._ValueList[0:len(TokenList)] = TokenList
199 if self._ValueList[1] == '':
200 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
201 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
202
203 ## DEFINE name=value parser
204 def _MacroParser(self):
205 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
206 MacroType = TokenList[0]
207 if len(TokenList) < 2 or TokenList[1] == '':
208 EdkLogger.error('Parser', FORMAT_INVALID, "No macro name/value given",
209 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
210 TokenList = GetSplitValueList(TokenList[1], TAB_EQUAL_SPLIT, 1)
211 if TokenList[0] == '':
212 EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
213 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
fd171542 214
215 # Macros defined in the command line override ones defined in the meta-data file
216 if not TokenList[0] in self._Macros:
217 if len(TokenList) == 1:
218 self._Macros[TokenList[0]] = ''
219 else:
220 # keep the macro definition for later use
221 self._Macros[TokenList[0]] = ReplaceMacro(TokenList[1], self._Macros, False)
30fdf114
LG
222
223 return TokenList[0], self._Macros[TokenList[0]]
224
225 ## [BuildOptions] section parser
226 def _BuildOptionParser(self):
227 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
228 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
229 if len(TokenList2) == 2:
230 self._ValueList[0] = TokenList2[0] # toolchain family
231 self._ValueList[1] = TokenList2[1] # keys
232 else:
233 self._ValueList[1] = TokenList[0]
234 if len(TokenList) == 2: # value
235 self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
236
237 if self._ValueList[1].count('_') != 4:
238 EdkLogger.error(
239 'Parser',
240 FORMAT_INVALID,
241 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
242 ExtraData=self._CurrentLine,
243 File=self.MetaFile,
244 Line=self._LineIndex+1
245 )
246
247 _SectionParser = {}
248 Table = property(_GetTable)
249 Finished = property(_GetFinished, _SetFinished)
250
251
252## INF file parser class
253#
254# @param FilePath The path of platform description file
255# @param FileType The raw data of DSC file
256# @param Table Database used to retrieve module/package information
257# @param Macros Macros used for replacement in file
258#
259class InfParser(MetaFileParser):
260 # INF file supported data types (one type per section)
261 DataType = {
262 TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
263 TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
264 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
265 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
266 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
267 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
268 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
269 TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
270 TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
271 TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
272 TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
273 TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
274 TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
275 TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
276 TAB_GUIDS.upper() : MODEL_EFI_GUID,
277 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
278 TAB_PPIS.upper() : MODEL_EFI_PPI,
279 TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
280 TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
281 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
282 }
283
284 ## Constructor of InfParser
285 #
286 # Initialize object of InfParser
287 #
288 # @param FilePath The path of module description file
289 # @param FileType The raw data of DSC file
290 # @param Table Database used to retrieve module/package information
291 # @param Macros Macros used for replacement in file
292 #
293 def __init__(self, FilePath, FileType, Table, Macros=None):
294 MetaFileParser.__init__(self, FilePath, FileType, Table, Macros)
295
296 ## Parser starter
297 def Start(self):
298 NmakeLine = ''
299 try:
300 self._Content = open(self.MetaFile, 'r').readlines()
301 except:
302 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
303
304 # parse the file line by line
305 IsFindBlockComment = False
306
307 for Index in range(0, len(self._Content)):
308 # skip empty, commented, block commented lines
309 Line = CleanString(self._Content[Index], AllowCppStyleComment=True)
310 NextLine = ''
311 if Index + 1 < len(self._Content):
312 NextLine = CleanString(self._Content[Index + 1])
313 if Line == '':
314 continue
315 if Line.find(DataType.TAB_COMMENT_R8_START) > -1:
316 IsFindBlockComment = True
317 continue
318 if Line.find(DataType.TAB_COMMENT_R8_END) > -1:
319 IsFindBlockComment = False
320 continue
321 if IsFindBlockComment:
322 continue
323
324 self._LineIndex = Index
325 self._CurrentLine = Line
326
327 # section header
328 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
329 self._SectionHeaderParser()
330 continue
331 # merge two lines specified by '\' in section NMAKE
332 elif self._SectionType == MODEL_META_DATA_NMAKE:
333 if Line[-1] == '\\':
334 if NextLine == '':
335 self._CurrentLine = NmakeLine + Line[0:-1]
336 NmakeLine = ''
337 else:
338 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
339 self._CurrentLine = NmakeLine + Line[0:-1]
340 NmakeLine = ''
341 else:
342 NmakeLine = NmakeLine + ' ' + Line[0:-1]
343 continue
344 else:
345 self._CurrentLine = NmakeLine + Line
346 NmakeLine = ''
347 elif Line.upper().startswith('DEFINE '):
348 # file private macros
349 self._MacroParser()
350 continue
351
352 # section content
353 self._ValueList = ['','','']
354 # parse current line, result will be put in self._ValueList
355 self._SectionParser[self._SectionType](self)
356 if self._ValueList == None:
357 continue
358 #
359 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
360 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
361 #
362 for Arch, Platform in self._Scope:
363 self._Store(self._SectionType,
364 self._ValueList[0],
365 self._ValueList[1],
366 self._ValueList[2],
367 Arch,
368 Platform,
369 self._Owner,
370 self._LineIndex+1,
371 -1,
372 self._LineIndex+1,
373 -1,
374 0
375 )
376 self._Done()
377
378 ## Data parser for the format in which there's path
379 #
380 # Only path can have macro used. So we need to replace them before use.
381 #
382 def _IncludeParser(self):
383 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
384 self._ValueList[0:len(TokenList)] = TokenList
385 if len(self._Macros) > 0:
386 for Index in range(0, len(self._ValueList)):
387 Value = self._ValueList[Index]
388 if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
389 Value = '$(EDK_SOURCE)' + Value[17:]
390 if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:
391 pass
392 elif Value.startswith('.'):
393 pass
394 elif Value.startswith('$('):
395 pass
396 else:
397 Value = '$(EFI_SOURCE)/' + Value
398
399 if Value == None or Value == '':
400 continue
401 self._ValueList[Index] = NormPath(Value, self._Macros)
402
403 ## Parse [Sources] section
404 #
405 # Only path can have macro used. So we need to replace them before use.
406 #
407 def _SourceFileParser(self):
408 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
409 self._ValueList[0:len(TokenList)] = TokenList
410 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
411 if 'COMPONENT_TYPE' in self._Macros:
412 if self._Macros['COMPONENT_TYPE'].upper() == 'ACPITABLE':
413 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
414 if self._Macros['BASE_NAME'] == 'Microcode':
415 pass
416 if len(self._Macros) > 0:
417 for Index in range(0, len(self._ValueList)):
418 Value = self._ValueList[Index]
419 if Value == None or Value == '':
420 continue
421 self._ValueList[Index] = NormPath(Value, self._Macros)
422
423 ## Parse [Binaries] section
424 #
425 # Only path can have macro used. So we need to replace them before use.
426 #
427 def _BinaryFileParser(self):
428 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
429 if len(TokenList) < 2:
430 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
431 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
432 File=self.MetaFile, Line=self._LineIndex+1)
433 if not TokenList[0]:
434 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
435 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
436 File=self.MetaFile, Line=self._LineIndex+1)
437 if not TokenList[1]:
438 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
439 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
440 File=self.MetaFile, Line=self._LineIndex+1)
441 self._ValueList[0:len(TokenList)] = TokenList
442 self._ValueList[1] = NormPath(self._ValueList[1], self._Macros)
443
444 ## [defines] section parser
445 def _DefineParser(self):
446 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
447 self._ValueList[0:len(TokenList)] = TokenList
448 self._Macros[TokenList[0]] = ReplaceMacro(TokenList[1], self._Macros, False)
449 if self._ValueList[1] == '':
450 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
451 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
452
453 ## [nmake] section parser (R8.x style only)
454 def _NmakeParser(self):
455 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
456 self._ValueList[0:len(TokenList)] = TokenList
457 # remove macros
458 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, False)
459 # remove self-reference in macro setting
460 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
461
462 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
463 def _PcdParser(self):
464 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
465 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
466 if len(TokenList) > 1:
467 self._ValueList[2] = TokenList[1]
468 if self._ValueList[0] == '' or self._ValueList[1] == '':
469 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
470 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
471 File=self.MetaFile, Line=self._LineIndex+1)
472
473 ## [depex] section parser
474 def _DepexParser(self):
475 self._ValueList[0:1] = [self._CurrentLine]
476
477 _SectionParser = {
478 MODEL_UNKNOWN : MetaFileParser._Skip,
479 MODEL_META_DATA_HEADER : _DefineParser,
480 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
481 MODEL_EFI_INCLUDE : _IncludeParser, # for R8.x modules
482 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for R8.x modules
483 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
484 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
485 MODEL_META_DATA_NMAKE : _NmakeParser, # for R8.x modules
486 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
487 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
488 MODEL_PCD_FEATURE_FLAG : _PcdParser,
489 MODEL_PCD_DYNAMIC_EX : _PcdParser,
490 MODEL_PCD_DYNAMIC : _PcdParser,
491 MODEL_EFI_SOURCE_FILE : _SourceFileParser,
492 MODEL_EFI_GUID : MetaFileParser._CommonParser,
493 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
494 MODEL_EFI_PPI : MetaFileParser._CommonParser,
495 MODEL_EFI_DEPEX : _DepexParser,
496 MODEL_EFI_BINARY_FILE : _BinaryFileParser,
497 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
498 }
499
500## DSC file parser class
501#
502# @param FilePath The path of platform description file
503# @param FileType The raw data of DSC file
504# @param Table Database used to retrieve module/package information
505# @param Macros Macros used for replacement in file
506# @param Owner Owner ID (for sub-section parsing)
507# @param From ID from which the data comes (for !INCLUDE directive)
508#
509class DscParser(MetaFileParser):
510 # DSC file supported data types (one type per section)
511 DataType = {
512 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
513 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
514 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
515 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
516 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
517 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
518 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
519 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
520 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
521 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
522 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
523 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
524 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
525 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
526 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
527 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,
528 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,
529 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
530 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
531 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
532 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
533 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
534 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
535 }
536
537 # sections which allow "!include" directive
538 _IncludeAllowedSection = [
539 TAB_LIBRARIES.upper(),
540 TAB_LIBRARY_CLASSES.upper(),
541 TAB_SKUIDS.upper(),
542 TAB_COMPONENTS.upper(),
543 TAB_BUILD_OPTIONS.upper(),
544 TAB_PCDS_FIXED_AT_BUILD_NULL.upper(),
545 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper(),
546 TAB_PCDS_FEATURE_FLAG_NULL.upper(),
547 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper(),
548 TAB_PCDS_DYNAMIC_HII_NULL.upper(),
549 TAB_PCDS_DYNAMIC_VPD_NULL.upper(),
550 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper(),
551 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper(),
552 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper(),
553 ]
554
555 # operators which can be used in "!if/!ifdef/!ifndef" directives
556 _OP_ = {
557 "!" : lambda a: not a,
558 "!=" : lambda a,b: a!=b,
559 "==" : lambda a,b: a==b,
560 ">" : lambda a,b: a>b,
561 "<" : lambda a,b: a<b,
562 "=>" : lambda a,b: a>=b,
563 ">=" : lambda a,b: a>=b,
564 "<=" : lambda a,b: a<=b,
565 "=<" : lambda a,b: a<=b,
566 }
567
568 ## Constructor of DscParser
569 #
570 # Initialize object of DscParser
571 #
572 # @param FilePath The path of platform description file
573 # @param FileType The raw data of DSC file
574 # @param Table Database used to retrieve module/package information
575 # @param Macros Macros used for replacement in file
576 # @param Owner Owner ID (for sub-section parsing)
577 # @param From ID from which the data comes (for !INCLUDE directive)
578 #
579 def __init__(self, FilePath, FileType, Table, Macros=None, Owner=-1, From=-1):
580 MetaFileParser.__init__(self, FilePath, FileType, Table, Macros, Owner, From)
581 # to store conditional directive evaluation result
582 self._Eval = Blist()
583
584 ## Parser starter
585 def Start(self):
586 try:
587 if self._Content == None:
588 self._Content = open(self.MetaFile, 'r').readlines()
589 except:
590 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
591
592 for Index in range(0, len(self._Content)):
593 Line = CleanString(self._Content[Index])
594 # skip empty line
595 if Line == '':
596 continue
597 self._CurrentLine = Line
598 self._LineIndex = Index
599
600 # section header
601 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
602 self._SectionHeaderParser()
603 continue
604 # subsection ending
605 elif Line[0] == '}':
606 self._InSubsection = False
607 self._SubsectionType = MODEL_UNKNOWN
608 self._SubsectionName = ''
609 self._Owner = -1
610 continue
611 # subsection header
612 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
613 self._SubsectionHeaderParser()
614 continue
615 # directive line
616 elif Line[0] == '!':
617 self._DirectiveParser()
618 continue
619 # file private macros
620 elif Line.upper().startswith('DEFINE '):
621 self._MacroParser()
622 continue
623 elif Line.upper().startswith('EDK_GLOBAL '):
624 (Name, Value) = self._MacroParser()
625 for Arch, ModuleType in self._Scope:
626 self._LastItem = self._Store(
627 MODEL_META_DATA_DEFINE,
628 Name,
629 Value,
630 '',
631 Arch,
632 'COMMON',
633 self._Owner,
634 self._From,
635 self._LineIndex+1,
636 -1,
637 self._LineIndex+1,
638 -1,
639 self._Enabled
640 )
641 continue
642
643 # section content
644 if self._InSubsection:
645 SectionType = self._SubsectionType
646 SectionName = self._SubsectionName
647 if self._Owner == -1:
648 self._Owner = self._LastItem
649 else:
650 SectionType = self._SectionType
651 SectionName = self._SectionName
652
653 self._ValueList = ['', '', '']
654 self._SectionParser[SectionType](self)
655 if self._ValueList == None:
656 continue
657
658 #
659 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
660 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
661 #
662 for Arch, ModuleType in self._Scope:
663 self._LastItem = self._Store(
664 SectionType,
665 self._ValueList[0],
666 self._ValueList[1],
667 self._ValueList[2],
668 Arch,
669 ModuleType,
670 self._Owner,
671 self._From,
672 self._LineIndex+1,
673 -1,
674 self._LineIndex+1,
675 -1,
676 self._Enabled
677 )
678 self._Done()
679
680 ## [defines] section parser
681 def _DefineParser(self):
682 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
683 if len(TokenList) < 2:
684 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
685 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
686 # 'FLASH_DEFINITION', 'OUTPUT_DIRECTORY' need special processing
687 if TokenList[0] in ['FLASH_DEFINITION', 'OUTPUT_DIRECTORY']:
688 TokenList[1] = NormPath(TokenList[1], self._Macros)
689 self._ValueList[0:len(TokenList)] = TokenList
690
691 ## <subsection_header> parser
692 def _SubsectionHeaderParser(self):
693 self._SubsectionName = self._CurrentLine[1:-1].upper()
694 if self._SubsectionName in self.DataType:
695 self._SubsectionType = self.DataType[self._SubsectionName]
696 else:
697 self._SubsectionType = MODEL_UNKNOWN
698 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
699 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
700
701 ## Directive statement parser
702 def _DirectiveParser(self):
703 self._ValueList = ['','','']
704 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
705 self._ValueList[0:len(TokenList)] = TokenList
706 DirectiveName = self._ValueList[0].upper()
707 if DirectiveName not in self.DataType:
708 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
709 File=self.MetaFile, Line=self._LineIndex+1)
710 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
711 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
712 File=self.MetaFile, Line=self._LineIndex+1,
713 ExtraData=self._CurrentLine)
714 # keep the directive in database first
715 self._LastItem = self._Store(
716 self.DataType[DirectiveName],
717 self._ValueList[0],
718 self._ValueList[1],
719 self._ValueList[2],
720 'COMMON',
721 'COMMON',
722 self._Owner,
723 self._From,
724 self._LineIndex + 1,
725 -1,
726 self._LineIndex + 1,
727 -1,
728 0
729 )
730
731 # process the directive
732 if DirectiveName == "!INCLUDE":
733 if not self._SectionName in self._IncludeAllowedSection:
734 EdkLogger.error("Parser", FORMAT_INVALID, File=self.MetaFile, Line=self._LineIndex+1,
735 ExtraData="'!include' is not allowed under section [%s]" % self._SectionName)
736 # the included file must be relative to the parsing file
737 IncludedFile = os.path.join(self._FileDir, self._ValueList[1])
738 Parser = DscParser(IncludedFile, self._FileType, self._Table, self._Macros, From=self._LastItem)
739 # set the parser status with current status
740 Parser._SectionName = self._SectionName
741 Parser._SectionType = self._SectionType
742 Parser._Scope = self._Scope
743 Parser._Enabled = self._Enabled
744 try:
745 Parser.Start()
746 except:
747 EdkLogger.error("Parser", PARSER_ERROR, File=self.MetaFile, Line=self._LineIndex+1,
748 ExtraData="Failed to parse content in file %s" % IncludedFile)
749 # update current status with sub-parser's status
750 self._SectionName = Parser._SectionName
751 self._SectionType = Parser._SectionType
752 self._Scope = Parser._Scope
753 self._Enabled = Parser._Enabled
754 else:
755 if DirectiveName in ["!IF", "!IFDEF", "!IFNDEF"]:
756 # evaluate the expression
757 Result = self._Evaluate(self._ValueList[1])
758 if DirectiveName == "!IFNDEF":
759 Result = not Result
760 self._Eval.append(Result)
761 elif DirectiveName in ["!ELSEIF"]:
762 # evaluate the expression
763 self._Eval[-1] = (not self._Eval[-1]) & self._Evaluate(self._ValueList[1])
764 elif DirectiveName in ["!ELSE"]:
765 self._Eval[-1] = not self._Eval[-1]
766 elif DirectiveName in ["!ENDIF"]:
767 if len(self._Eval) > 0:
768 self._Eval.pop()
769 else:
770 EdkLogger.error("Parser", FORMAT_INVALID, "!IF..[!ELSE]..!ENDIF doesn't match",
771 File=self.MetaFile, Line=self._LineIndex+1)
772 if self._Eval.Result == False:
773 self._Enabled = 0 - len(self._Eval)
774 else:
775 self._Enabled = len(self._Eval)
776
777 ## Evaludate the value of expression in "if/ifdef/ifndef" directives
778 def _Evaluate(self, Expression):
779 TokenList = Expression.split()
780 TokenNumber = len(TokenList)
781 # one operand, guess it's just a macro name
782 if TokenNumber == 1:
783 return TokenList[0] in self._Macros
784 # two operands, suppose it's "!xxx" format
785 elif TokenNumber == 2:
786 Op = TokenList[0]
787 if Op not in self._OP_:
788 EdkLogger.error('Parser', FORMAT_INVALID, "Unsupported operator [%s]" % Op, File=self.MetaFile,
789 Line=self._LineIndex+1, ExtraData=Expression)
790 if TokenList[1].upper() == 'TRUE':
791 Value = True
792 else:
793 Value = False
794 return self._OP_[Op](Value)
795 # three operands
796 elif TokenNumber == 3:
797 Name = TokenList[0]
798 if Name not in self._Macros:
799 return False
800 Value = TokenList[2]
801 if Value[0] in ["'", '"'] and Value[-1] in ["'", '"']:
802 Value = Value[1:-1]
803 Op = TokenList[1]
804 if Op not in self._OP_:
805 EdkLogger.error('Parser', FORMAT_INVALID, "Unsupported operator [%s]" % Op, File=self.MetaFile,
806 Line=self._LineIndex+1, ExtraData=Expression)
807 return self._OP_[Op](self._Macros[Name], Value)
808 else:
809 EdkLogger.error('Parser', FORMAT_INVALID, File=self.MetaFile, Line=self._LineIndex+1,
810 ExtraData=Expression)
811
812 ## PCD sections parser
813 #
814 # [PcdsFixedAtBuild]
815 # [PcdsPatchableInModule]
816 # [PcdsFeatureFlag]
817 # [PcdsDynamicEx
818 # [PcdsDynamicExDefault]
819 # [PcdsDynamicExVpd]
820 # [PcdsDynamicExHii]
821 # [PcdsDynamic]
822 # [PcdsDynamicDefault]
823 # [PcdsDynamicVpd]
824 # [PcdsDynamicHii]
825 #
826 def _PcdParser(self):
827 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
828 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
829 if len(TokenList) == 2:
830 self._ValueList[2] = TokenList[1]
831 if self._ValueList[0] == '' or self._ValueList[1] == '':
832 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
833 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
834 File=self.MetaFile, Line=self._LineIndex+1)
835 if self._ValueList[2] == '':
836 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
837 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
838 File=self.MetaFile, Line=self._LineIndex+1)
839
840 ## [components] section parser
841 def _ComponentParser(self):
842 if self._CurrentLine[-1] == '{':
843 self._ValueList[0] = self._CurrentLine[0:-1].strip()
844 self._InSubsection = True
845 else:
846 self._ValueList[0] = self._CurrentLine
847 if len(self._Macros) > 0:
848 self._ValueList[0] = NormPath(self._ValueList[0], self._Macros)
849
850 def _LibraryClassParser(self):
851 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
852 if len(TokenList) < 2:
853 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
854 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
855 File=self.MetaFile, Line=self._LineIndex+1)
856 if TokenList[0] == '':
857 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
858 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
859 File=self.MetaFile, Line=self._LineIndex+1)
860 if TokenList[1] == '':
861 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
862 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
863 File=self.MetaFile, Line=self._LineIndex+1)
864 self._ValueList[0:len(TokenList)] = TokenList
865 if len(self._Macros) > 0:
866 self._ValueList[1] = NormPath(self._ValueList[1], self._Macros)
867
868 def _CompponentSourceOverridePathParser(self):
869 if len(self._Macros) > 0:
870 self._ValueList[0] = NormPath(self._CurrentLine, self._Macros)
871
872 _SectionParser = {
873 MODEL_META_DATA_HEADER : _DefineParser,
874 MODEL_EFI_SKU_ID : MetaFileParser._CommonParser,
875 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._PathParser,
876 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
877 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
878 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
879 MODEL_PCD_FEATURE_FLAG : _PcdParser,
880 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
881 MODEL_PCD_DYNAMIC_HII : _PcdParser,
882 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
883 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
884 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
885 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
886 MODEL_META_DATA_COMPONENT : _ComponentParser,
887 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,
888 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
889 MODEL_UNKNOWN : MetaFileParser._Skip,
890 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
891 }
892
893## DEC file parser class
894#
895# @param FilePath The path of platform description file
896# @param FileType The raw data of DSC file
897# @param Table Database used to retrieve module/package information
898# @param Macros Macros used for replacement in file
899#
900class DecParser(MetaFileParser):
901 # DEC file supported data types (one type per section)
902 DataType = {
903 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
904 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
905 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
906 TAB_GUIDS.upper() : MODEL_EFI_GUID,
907 TAB_PPIS.upper() : MODEL_EFI_PPI,
908 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
909 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
910 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
911 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
912 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
913 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
914 }
915
916 ## Constructor of DecParser
917 #
918 # Initialize object of DecParser
919 #
920 # @param FilePath The path of platform description file
921 # @param FileType The raw data of DSC file
922 # @param Table Database used to retrieve module/package information
923 # @param Macros Macros used for replacement in file
924 #
925 def __init__(self, FilePath, FileType, Table, Macro=None):
926 MetaFileParser.__init__(self, FilePath, FileType, Table, Macro, -1)
927
928 ## Parser starter
929 def Start(self):
930 try:
931 if self._Content == None:
932 self._Content = open(self.MetaFile, 'r').readlines()
933 except:
934 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
935
936 for Index in range(0, len(self._Content)):
937 Line = CleanString(self._Content[Index])
938 # skip empty line
939 if Line == '':
940 continue
941 self._CurrentLine = Line
942 self._LineIndex = Index
943
944 # section header
945 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
946 self._SectionHeaderParser()
947 continue
948 elif Line.startswith('DEFINE '):
949 self._MacroParser()
950 continue
951 elif len(self._SectionType) == 0:
952 continue
953
954 # section content
955 self._ValueList = ['','','']
956 self._SectionParser[self._SectionType[0]](self)
957 if self._ValueList == None:
958 continue
959
960 #
961 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
962 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
963 #
964 for Arch, ModuleType, Type in self._Scope:
965 self._LastItem = self._Store(
966 Type,
967 self._ValueList[0],
968 self._ValueList[1],
969 self._ValueList[2],
970 Arch,
971 ModuleType,
972 self._Owner,
973 self._LineIndex+1,
974 -1,
975 self._LineIndex+1,
976 -1,
977 0
978 )
979 self._Done()
980
981 ## Section header parser
982 #
983 # The section header is always in following format:
984 #
985 # [section_name.arch<.platform|module_type>]
986 #
987 def _SectionHeaderParser(self):
988 self._Scope = []
989 self._SectionName = ''
990 self._SectionType = []
991 ArchList = set()
992 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
993 if Item == '':
994 continue
995 ItemList = GetSplitValueList(Item, TAB_SPLIT)
996
997 # different types of PCD are permissible in one section
998 self._SectionName = ItemList[0].upper()
999 if self._SectionName in self.DataType:
1000 if self.DataType[self._SectionName] not in self._SectionType:
1001 self._SectionType.append(self.DataType[self._SectionName])
1002 else:
1003 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
1004 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
1005 continue
1006
1007 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1008 EdkLogger.error(
1009 'Parser',
1010 FORMAT_INVALID,
1011 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1012 File=self.MetaFile,
1013 Line=self._LineIndex+1,
1014 ExtraData=self._CurrentLine
1015 )
1016 # S1 is always Arch
1017 if len(ItemList) > 1:
1018 S1 = ItemList[1].upper()
1019 else:
1020 S1 = 'COMMON'
1021 ArchList.add(S1)
1022 # S2 may be Platform or ModuleType
1023 if len(ItemList) > 2:
1024 S2 = ItemList[2].upper()
1025 else:
1026 S2 = 'COMMON'
1027 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1028 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1029
1030 # 'COMMON' must not be used with specific ARCHs at the same section
1031 if 'COMMON' in ArchList and len(ArchList) > 1:
1032 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1033 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
1034
1035 ## [guids], [ppis] and [protocols] section parser
1036 def _GuidParser(self):
1037 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1038 if len(TokenList) < 2:
1039 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1040 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1041 File=self.MetaFile, Line=self._LineIndex+1)
1042 if TokenList[0] == '':
1043 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1044 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1045 File=self.MetaFile, Line=self._LineIndex+1)
1046 if TokenList[1] == '':
1047 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1048 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1049 File=self.MetaFile, Line=self._LineIndex+1)
1050 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1051 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1052 ExtraData=self._CurrentLine + \
1053 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1054 File=self.MetaFile, Line=self._LineIndex+1)
1055 self._ValueList[0] = TokenList[0]
1056 self._ValueList[1] = TokenList[1]
1057
1058 ## PCD sections parser
1059 #
1060 # [PcdsFixedAtBuild]
1061 # [PcdsPatchableInModule]
1062 # [PcdsFeatureFlag]
1063 # [PcdsDynamicEx
1064 # [PcdsDynamic]
1065 #
1066 def _PcdParser(self):
1067 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1068 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1069 # check PCD information
1070 if self._ValueList[0] == '' or self._ValueList[1] == '':
1071 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1072 ExtraData=self._CurrentLine + \
1073 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1074 File=self.MetaFile, Line=self._LineIndex+1)
1075 # check PCD datum information
1076 if len(TokenList) < 2 or TokenList[1] == '':
1077 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
1078 ExtraData=self._CurrentLine + \
1079 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1080 File=self.MetaFile, Line=self._LineIndex+1)
1081
1082 ValueList = GetSplitValueList(TokenList[1])
1083 # check if there's enough datum information given
1084 if len(ValueList) != 3:
1085 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
1086 ExtraData=self._CurrentLine + \
1087 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1088 File=self.MetaFile, Line=self._LineIndex+1)
1089 # check default value
1090 if ValueList[0] == '':
1091 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
1092 ExtraData=self._CurrentLine + \
1093 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1094 File=self.MetaFile, Line=self._LineIndex+1)
1095 # check datum type
1096 if ValueList[1] == '':
1097 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
1098 ExtraData=self._CurrentLine + \
1099 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1100 File=self.MetaFile, Line=self._LineIndex+1)
1101 # check token of the PCD
1102 if ValueList[2] == '':
1103 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
1104 ExtraData=self._CurrentLine + \
1105 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1106 File=self.MetaFile, Line=self._LineIndex+1)
1107 # check format of default value against the datum type
1108 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
1109 if not IsValid:
1110 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
1111 File=self.MetaFile, Line=self._LineIndex+1)
1112 self._ValueList[2] = TokenList[1]
1113
1114 _SectionParser = {
1115 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
1116 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
1117 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
1118 MODEL_EFI_GUID : _GuidParser,
1119 MODEL_EFI_PPI : _GuidParser,
1120 MODEL_EFI_PROTOCOL : _GuidParser,
1121 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1122 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1123 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1124 MODEL_PCD_DYNAMIC : _PcdParser,
1125 MODEL_PCD_DYNAMIC_EX : _PcdParser,
1126 MODEL_UNKNOWN : MetaFileParser._Skip,
1127 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1128 }
1129
1130##
1131#
1132# This acts like the main() function for the script, unless it is 'import'ed into another
1133# script.
1134#
1135if __name__ == '__main__':
1136 pass
1137