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