]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/MetaFileParser.py
470cfed5b6a35f9243196ef6288f6dfa0ec17e1a
[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 import Common.LongFilePathOs as os
19 import re
20 import time
21 import copy
22 from hashlib import md5
23
24 import Common.EdkLogger as EdkLogger
25 import Common.GlobalData as GlobalData
26
27 from CommonDataClass.DataClass import *
28 from Common.DataType import *
29 from Common.StringUtils import *
30 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue
31 from Common.Expression import *
32 from CommonDataClass.Exceptions import *
33 from Common.LongFilePathSupport import OpenLongFilePath as open
34 from collections import defaultdict
35 from .MetaFileTable import MetaFileStorage
36 from .MetaFileCommentParser import CheckInfComment
37
38 ## RegEx for finding file versions
39 hexVersionPattern = re.compile(r'0[xX][\da-f-A-F]{5,8}')
40 decVersionPattern = re.compile(r'\d+\.\d+')
41
42 ## A decorator used to parse macro definition
43 def ParseMacro(Parser):
44 def MacroParser(self):
45 Match = gMacroDefPattern.match(self._CurrentLine)
46 if not Match:
47 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
48 Parser(self)
49 return
50
51 TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)
52 # Syntax check
53 if not TokenList[0]:
54 EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
55 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
56 if len(TokenList) < 2:
57 TokenList.append('')
58
59 Type = Match.group(1)
60 Name, Value = TokenList
61 # Global macros can be only defined via environment variable
62 if Name in GlobalData.gGlobalDefines:
63 EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
64 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
65 # Only upper case letters, digit and '_' are allowed
66 if not gMacroNamePattern.match(Name):
67 EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
68 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
69
70 Value = ReplaceMacro(Value, self._Macros)
71 if Type in self.DataType:
72 self._ItemType = self.DataType[Type]
73 else:
74 self._ItemType = MODEL_META_DATA_DEFINE
75 # DEFINE defined macros
76 if Type == TAB_DSC_DEFINES_DEFINE:
77 #
78 # First judge whether this DEFINE is in conditional directive statements or not.
79 #
80 if isinstance(self, DscParser) and self._InDirective > -1:
81 pass
82 else:
83 if isinstance(self, DecParser):
84 if MODEL_META_DATA_HEADER in self._SectionType:
85 self._FileLocalMacros[Name] = Value
86 else:
87 self._ConstructSectionMacroDict(Name, Value)
88 elif self._SectionType == MODEL_META_DATA_HEADER:
89 self._FileLocalMacros[Name] = Value
90 else:
91 self._ConstructSectionMacroDict(Name, Value)
92
93 # EDK_GLOBAL defined macros
94 elif not isinstance(self, DscParser):
95 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
96 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
97 elif self._SectionType != MODEL_META_DATA_HEADER:
98 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
99 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
100 elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
101 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
102 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
103
104 self._ValueList = [Type, Name, Value]
105
106 return MacroParser
107
108 ## Base class of parser
109 #
110 # This class is used for derivation purpose. The specific parser for one kind
111 # type file must derive this class and implement some public interfaces.
112 #
113 # @param FilePath The path of platform description file
114 # @param FileType The raw data of DSC file
115 # @param Table Database used to retrieve module/package information
116 # @param Macros Macros used for replacement in file
117 # @param Owner Owner ID (for sub-section parsing)
118 # @param From ID from which the data comes (for !INCLUDE directive)
119 #
120 class MetaFileParser(object):
121 # data type (file content) for specific file type
122 DataType = {}
123
124 # Parser objects used to implement singleton
125 MetaFiles = {}
126
127 ## Factory method
128 #
129 # One file, one parser object. This factory method makes sure that there's
130 # only one object constructed for one meta file.
131 #
132 # @param Class class object of real AutoGen class
133 # (InfParser, DecParser or DscParser)
134 # @param FilePath The path of meta file
135 # @param *args The specific class related parameters
136 # @param **kwargs The specific class related dict parameters
137 #
138 def __new__(Class, FilePath, *args, **kwargs):
139 if FilePath in Class.MetaFiles:
140 return Class.MetaFiles[FilePath]
141 else:
142 ParserObject = super().__new__(Class)
143 Class.MetaFiles[FilePath] = ParserObject
144 return ParserObject
145
146 ## Constructor of MetaFileParser
147 #
148 # Initialize object of MetaFileParser
149 #
150 # @param FilePath The path of platform description file
151 # @param FileType The raw data of DSC file
152 # @param Arch Default Arch value for filtering sections
153 # @param Table Database used to retrieve module/package information
154 # @param Owner Owner ID (for sub-section parsing)
155 # @param From ID from which the data comes (for !INCLUDE directive)
156 #
157 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
158 self._Table = Table
159 self._RawTable = Table
160 self._Arch = Arch
161 self._FileType = FileType
162 self.MetaFile = FilePath
163 self._FileDir = self.MetaFile.Dir
164 self._Defines = {}
165 self._FileLocalMacros = {}
166 self._SectionsMacroDict = defaultdict(dict)
167
168 # for recursive parsing
169 self._Owner = [Owner]
170 self._From = From
171
172 # parsr status for parsing
173 self._ValueList = ['', '', '', '', '']
174 self._Scope = []
175 self._LineIndex = 0
176 self._CurrentLine = ''
177 self._SectionType = MODEL_UNKNOWN
178 self._SectionName = ''
179 self._InSubsection = False
180 self._SubsectionType = MODEL_UNKNOWN
181 self._SubsectionName = ''
182 self._ItemType = MODEL_UNKNOWN
183 self._LastItem = -1
184 self._Enabled = 0
185 self._Finished = False
186 self._PostProcessed = False
187 # Different version of meta-file has different way to parse.
188 self._Version = 0
189 self._GuidDict = {} # for Parser PCD value {GUID(gTokeSpaceGuidName)}
190
191 ## Store the parsed data in table
192 def _Store(self, *Args):
193 return self._Table.Insert(*Args)
194
195 ## Virtual method for starting parse
196 def Start(self):
197 raise NotImplementedError
198
199 ## Notify a post-process is needed
200 def DoPostProcess(self):
201 self._PostProcessed = False
202
203 ## Set parsing complete flag in both class and table
204 def _Done(self):
205 self._Finished = True
206 ## Do not set end flag when processing included files
207 if self._From == -1:
208 self._Table.SetEndFlag()
209
210 def _PostProcess(self):
211 self._PostProcessed = True
212
213 ## Get the parse complete flag
214 @property
215 def Finished(self):
216 return self._Finished
217
218 ## Set the complete flag
219 @Finished.setter
220 def Finished(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
420 @property
421 def _Macros(self):
422 Macros = {}
423 Macros.update(self._FileLocalMacros)
424 Macros.update(self._GetApplicableSectionMacro())
425 return Macros
426
427 ## Construct section Macro dict
428 def _ConstructSectionMacroDict(self, Name, Value):
429 ScopeKey = [(Scope[0], Scope[1], Scope[2]) for Scope in self._Scope]
430 ScopeKey = tuple(ScopeKey)
431 #
432 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
433 # As Pcd section macro usage is not alllowed, so here it is safe
434 #
435 if isinstance(self, DecParser):
436 SectionDictKey = self._SectionType[0], ScopeKey
437 else:
438 SectionDictKey = self._SectionType, ScopeKey
439
440 self._SectionsMacroDict[SectionDictKey][Name] = Value
441
442 ## Get section Macros that are applicable to current line, which may come from other sections
443 ## that share the same name while scope is wider
444 def _GetApplicableSectionMacro(self):
445 Macros = {}
446
447 ComComMacroDict = {}
448 ComSpeMacroDict = {}
449 SpeSpeMacroDict = {}
450
451 ActiveSectionType = self._SectionType
452 if isinstance(self, DecParser):
453 ActiveSectionType = self._SectionType[0]
454
455 for (SectionType, Scope) in self._SectionsMacroDict:
456 if SectionType != ActiveSectionType:
457 continue
458
459 for ActiveScope in self._Scope:
460 Scope0, Scope1, Scope2= ActiveScope[0], ActiveScope[1], ActiveScope[2]
461 if(Scope0, Scope1, Scope2) not in Scope:
462 break
463 else:
464 SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
465
466 for ActiveScope in self._Scope:
467 Scope0, Scope1, Scope2 = ActiveScope[0], ActiveScope[1], ActiveScope[2]
468 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:
469 break
470 else:
471 ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
472
473 if (TAB_COMMON, TAB_COMMON, TAB_COMMON) in Scope:
474 ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
475
476 Macros.update(ComComMacroDict)
477 Macros.update(ComSpeMacroDict)
478 Macros.update(SpeSpeMacroDict)
479
480 return Macros
481
482 _SectionParser = {}
483
484 ## INF file parser class
485 #
486 # @param FilePath The path of platform description file
487 # @param FileType The raw data of DSC file
488 # @param Table Database used to retrieve module/package information
489 # @param Macros Macros used for replacement in file
490 #
491 class InfParser(MetaFileParser):
492 # INF file supported data types (one type per section)
493 DataType = {
494 TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
495 TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
496 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
497 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
498 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
499 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
500 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
501 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
502 TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
503 TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
504 TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
505 TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
506 TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
507 TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
508 TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
509 TAB_GUIDS.upper() : MODEL_EFI_GUID,
510 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
511 TAB_PPIS.upper() : MODEL_EFI_PPI,
512 TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
513 TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
514 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
515 }
516
517 ## Constructor of InfParser
518 #
519 # Initialize object of InfParser
520 #
521 # @param FilePath The path of module description file
522 # @param FileType The raw data of DSC file
523 # @param Arch Default Arch value for filtering sections
524 # @param Table Database used to retrieve module/package information
525 #
526 def __init__(self, FilePath, FileType, Arch, Table):
527 # prevent re-initialization
528 if hasattr(self, "_Table"):
529 return
530 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)
531 self.PcdsDict = {}
532
533 ## Parser starter
534 def Start(self):
535 NmakeLine = ''
536 Content = ''
537 try:
538 Content = open(str(self.MetaFile), 'r').readlines()
539 except:
540 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
541
542 # parse the file line by line
543 IsFindBlockComment = False
544 GetHeaderComment = False
545 TailComments = []
546 SectionComments = []
547 Comments = []
548
549 for Index in range(0, len(Content)):
550 # skip empty, commented, block commented lines
551 Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)
552 NextLine = ''
553 if Index + 1 < len(Content):
554 NextLine, NextComment = CleanString2(Content[Index + 1])
555 if Line == '':
556 if Comment:
557 Comments.append((Comment, Index + 1))
558 elif GetHeaderComment:
559 SectionComments.extend(Comments)
560 Comments = []
561 continue
562 if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:
563 IsFindBlockComment = True
564 continue
565 if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:
566 IsFindBlockComment = False
567 continue
568 if IsFindBlockComment:
569 continue
570
571 self._LineIndex = Index
572 self._CurrentLine = Line
573
574 # section header
575 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
576 if not GetHeaderComment:
577 for Cmt, LNo in Comments:
578 self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', TAB_COMMON,
579 TAB_COMMON, self._Owner[-1], LNo, -1, LNo, -1, 0)
580 GetHeaderComment = True
581 else:
582 TailComments.extend(SectionComments + Comments)
583 Comments = []
584 self._SectionHeaderParser()
585 # Check invalid sections
586 if self._Version < 0x00010005:
587 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
588 MODEL_EFI_LIBRARY_CLASS,
589 MODEL_META_DATA_PACKAGE,
590 MODEL_PCD_FIXED_AT_BUILD,
591 MODEL_PCD_PATCHABLE_IN_MODULE,
592 MODEL_PCD_FEATURE_FLAG,
593 MODEL_PCD_DYNAMIC_EX,
594 MODEL_PCD_DYNAMIC,
595 MODEL_EFI_GUID,
596 MODEL_EFI_PROTOCOL,
597 MODEL_EFI_PPI,
598 MODEL_META_DATA_USER_EXTENSION]:
599 EdkLogger.error('Parser', FORMAT_INVALID,
600 "Section [%s] is not allowed in inf file without version" % (self._SectionName),
601 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
602 elif self._SectionType in [MODEL_EFI_INCLUDE,
603 MODEL_EFI_LIBRARY_INSTANCE,
604 MODEL_META_DATA_NMAKE]:
605 EdkLogger.error('Parser', FORMAT_INVALID,
606 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
607 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
608 continue
609 # merge two lines specified by '\' in section NMAKE
610 elif self._SectionType == MODEL_META_DATA_NMAKE:
611 if Line[-1] == '\\':
612 if NextLine == '':
613 self._CurrentLine = NmakeLine + Line[0:-1]
614 NmakeLine = ''
615 else:
616 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
617 self._CurrentLine = NmakeLine + Line[0:-1]
618 NmakeLine = ''
619 else:
620 NmakeLine = NmakeLine + ' ' + Line[0:-1]
621 continue
622 else:
623 self._CurrentLine = NmakeLine + Line
624 NmakeLine = ''
625
626 # section content
627 self._ValueList = ['', '', '']
628 # parse current line, result will be put in self._ValueList
629 self._SectionParser[self._SectionType](self)
630 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
631 self._ItemType = -1
632 Comments = []
633 continue
634 if Comment:
635 Comments.append((Comment, Index + 1))
636 if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:
637 CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)
638 #
639 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
640 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
641 #
642 for Arch, Platform, _ in self._Scope:
643 LastItem = self._Store(self._SectionType,
644 self._ValueList[0],
645 self._ValueList[1],
646 self._ValueList[2],
647 Arch,
648 Platform,
649 self._Owner[-1],
650 self._LineIndex + 1,
651 - 1,
652 self._LineIndex + 1,
653 - 1,
654 0
655 )
656 for Comment, LineNo in Comments:
657 self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,
658 LastItem, LineNo, -1, LineNo, -1, 0)
659 Comments = []
660 SectionComments = []
661 TailComments.extend(SectionComments + Comments)
662 if IsFindBlockComment:
663 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
664 File=self.MetaFile)
665
666 # If there are tail comments in INF file, save to database whatever the comments are
667 for Comment in TailComments:
668 self._Store(MODEL_META_DATA_TAIL_COMMENT, Comment[0], '', '', TAB_COMMON,
669 TAB_COMMON, self._Owner[-1], -1, -1, -1, -1, 0)
670 self._Done()
671
672 ## Data parser for the format in which there's path
673 #
674 # Only path can have macro used. So we need to replace them before use.
675 #
676 def _IncludeParser(self):
677 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
678 self._ValueList[0:len(TokenList)] = TokenList
679 Macros = self._Macros
680 if Macros:
681 for Index in range(0, len(self._ValueList)):
682 Value = self._ValueList[Index]
683 if not Value:
684 continue
685
686 if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
687 Value = '$(EDK_SOURCE)' + Value[17:]
688 if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:
689 pass
690 elif Value.startswith('.'):
691 pass
692 elif Value.startswith('$('):
693 pass
694 else:
695 Value = '$(EFI_SOURCE)/' + Value
696
697 self._ValueList[Index] = ReplaceMacro(Value, Macros)
698
699 ## Parse [Sources] section
700 #
701 # Only path can have macro used. So we need to replace them before use.
702 #
703 @ParseMacro
704 def _SourceFileParser(self):
705 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
706 self._ValueList[0:len(TokenList)] = TokenList
707 Macros = self._Macros
708 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
709 if 'COMPONENT_TYPE' in Macros:
710 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
711 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
712 if self._Defines['BASE_NAME'] == 'Microcode':
713 pass
714 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
715
716 ## Parse [Binaries] section
717 #
718 # Only path can have macro used. So we need to replace them before use.
719 #
720 @ParseMacro
721 def _BinaryFileParser(self):
722 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
723 if len(TokenList) < 2:
724 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
725 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
726 File=self.MetaFile, Line=self._LineIndex + 1)
727 if not TokenList[0]:
728 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
729 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
730 File=self.MetaFile, Line=self._LineIndex + 1)
731 if not TokenList[1]:
732 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
733 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
734 File=self.MetaFile, Line=self._LineIndex + 1)
735 self._ValueList[0:len(TokenList)] = TokenList
736 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
737
738 ## [nmake] section parser (Edk.x style only)
739 def _NmakeParser(self):
740 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
741 self._ValueList[0:len(TokenList)] = TokenList
742 # remove macros
743 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
744 # remove self-reference in macro setting
745 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
746
747 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
748 @ParseMacro
749 def _PcdParser(self):
750 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
751 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
752 if len(ValueList) != 2:
753 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
754 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
755 File=self.MetaFile, Line=self._LineIndex + 1)
756 self._ValueList[0:1] = ValueList
757 if len(TokenList) > 1:
758 self._ValueList[2] = TokenList[1]
759 if self._ValueList[0] == '' or self._ValueList[1] == '':
760 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
761 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
762 File=self.MetaFile, Line=self._LineIndex + 1)
763
764 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
765 if self._ValueList[2] != '':
766 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
767 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
768 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
769 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
770 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
771 if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:
772 self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType
773 elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:
774 EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",
775 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
776 File=self.MetaFile, Line=self._LineIndex + 1)
777
778 ## [depex] section parser
779 @ParseMacro
780 def _DepexParser(self):
781 self._ValueList[0:1] = [self._CurrentLine]
782
783 _SectionParser = {
784 MODEL_UNKNOWN : MetaFileParser._Skip,
785 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
786 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
787 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules
788 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules
789 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
790 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
791 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules
792 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
793 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
794 MODEL_PCD_FEATURE_FLAG : _PcdParser,
795 MODEL_PCD_DYNAMIC_EX : _PcdParser,
796 MODEL_PCD_DYNAMIC : _PcdParser,
797 MODEL_EFI_SOURCE_FILE : _SourceFileParser,
798 MODEL_EFI_GUID : MetaFileParser._CommonParser,
799 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
800 MODEL_EFI_PPI : MetaFileParser._CommonParser,
801 MODEL_EFI_DEPEX : _DepexParser,
802 MODEL_EFI_BINARY_FILE : _BinaryFileParser,
803 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
804 }
805
806 ## DSC file parser class
807 #
808 # @param FilePath The path of platform description file
809 # @param FileType The raw data of DSC file
810 # @param Table Database used to retrieve module/package information
811 # @param Macros Macros used for replacement in file
812 # @param Owner Owner ID (for sub-section parsing)
813 # @param From ID from which the data comes (for !INCLUDE directive)
814 #
815 class DscParser(MetaFileParser):
816 # DSC file supported data types (one type per section)
817 DataType = {
818 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
819 TAB_DEFAULT_STORES.upper() : MODEL_EFI_DEFAULT_STORES,
820 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
821 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
822 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
823 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
824 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
825 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
826 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
827 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
828 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
829 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
830 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
831 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
832 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
833 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
834 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,
835 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
836 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,
837 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,
838 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
839 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
840 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
841 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
842 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
843 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
844 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
845 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,
846 }
847
848 # Valid names in define section
849 DefineKeywords = [
850 "DSC_SPECIFICATION",
851 "PLATFORM_NAME",
852 "PLATFORM_GUID",
853 "PLATFORM_VERSION",
854 "SKUID_IDENTIFIER",
855 "PCD_INFO_GENERATION",
856 "PCD_VAR_CHECK_GENERATION",
857 "SUPPORTED_ARCHITECTURES",
858 "BUILD_TARGETS",
859 "OUTPUT_DIRECTORY",
860 "FLASH_DEFINITION",
861 "BUILD_NUMBER",
862 "RFC_LANGUAGES",
863 "ISO_LANGUAGES",
864 "TIME_STAMP_FILE",
865 "VPD_TOOL_GUID",
866 "FIX_LOAD_TOP_MEMORY_ADDRESS",
867 "PREBUILD",
868 "POSTBUILD"
869 ]
870
871 SubSectionDefineKeywords = [
872 "FILE_GUID"
873 ]
874
875 SymbolPattern = ValueExpression.SymbolPattern
876
877 IncludedFiles = set()
878
879 ## Constructor of DscParser
880 #
881 # Initialize object of DscParser
882 #
883 # @param FilePath The path of platform description file
884 # @param FileType The raw data of DSC file
885 # @param Arch Default Arch value for filtering sections
886 # @param Table Database used to retrieve module/package information
887 # @param Owner Owner ID (for sub-section parsing)
888 # @param From ID from which the data comes (for !INCLUDE directive)
889 #
890 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
891 # prevent re-initialization
892 if hasattr(self, "_Table") and self._Table is Table:
893 return
894 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)
895 self._Version = 0x00010005 # Only EDK2 dsc file is supported
896 # to store conditional directive evaluation result
897 self._DirectiveStack = []
898 self._DirectiveEvalStack = []
899 self._Enabled = 1
900
901 #
902 # Specify whether current line is in uncertain condition
903 #
904 self._InDirective = -1
905
906 # Final valid replacable symbols
907 self._Symbols = {}
908 #
909 # Map the ID between the original table and new table to track
910 # the owner item
911 #
912 self._IdMapping = {-1:-1}
913
914 ## Parser starter
915 def Start(self):
916 Content = ''
917 try:
918 Content = open(str(self.MetaFile), 'r').readlines()
919 except:
920 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
921
922 OwnerId = {}
923 for Index in range(0, len(Content)):
924 Line = CleanString(Content[Index])
925 # skip empty line
926 if Line == '':
927 continue
928
929 self._CurrentLine = Line
930 self._LineIndex = Index
931 if self._InSubsection and self._Owner[-1] == -1:
932 self._Owner.append(self._LastItem)
933
934 # section header
935 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
936 self._SectionType = MODEL_META_DATA_SECTION_HEADER
937 # subsection ending
938 elif Line[0] == '}' and self._InSubsection:
939 self._InSubsection = False
940 self._SubsectionType = MODEL_UNKNOWN
941 self._SubsectionName = ''
942 self._Owner[-1] = -1
943 OwnerId.clear()
944 continue
945 # subsection header
946 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
947 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
948 # directive line
949 elif Line[0] == '!':
950 TokenList = GetSplitValueList(Line, ' ', 1)
951 if TokenList[0] == TAB_INCLUDE:
952 for Arch, ModuleType, DefaultStore in self._Scope:
953 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
954 self._Owner[-1] = OwnerId[Arch]
955 self._DirectiveParser()
956 else:
957 self._DirectiveParser()
958 continue
959 if Line[0] == TAB_OPTION_START and not self._InSubsection:
960 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)
961
962 if self._InSubsection:
963 SectionType = self._SubsectionType
964 else:
965 SectionType = self._SectionType
966 self._ItemType = SectionType
967
968 self._ValueList = ['', '', '']
969 self._SectionParser[SectionType](self)
970 if self._ValueList is None:
971 continue
972 #
973 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
974 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
975 #
976 for Arch, ModuleType, DefaultStore in self._Scope:
977 Owner = self._Owner[-1]
978 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
979 Owner = OwnerId[Arch]
980 self._LastItem = self._Store(
981 self._ItemType,
982 self._ValueList[0],
983 self._ValueList[1],
984 self._ValueList[2],
985 Arch,
986 ModuleType,
987 DefaultStore,
988 Owner,
989 self._From,
990 self._LineIndex + 1,
991 - 1,
992 self._LineIndex + 1,
993 - 1,
994 self._Enabled
995 )
996 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
997 OwnerId[Arch] = self._LastItem
998
999 if self._DirectiveStack:
1000 Type, Line, Text = self._DirectiveStack[-1]
1001 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
1002 ExtraData=Text, File=self.MetaFile, Line=Line)
1003 self._Done()
1004
1005 ## <subsection_header> parser
1006 def _SubsectionHeaderParser(self):
1007 self._SubsectionName = self._CurrentLine[1:-1].upper()
1008 if self._SubsectionName in self.DataType:
1009 self._SubsectionType = self.DataType[self._SubsectionName]
1010 else:
1011 self._SubsectionType = MODEL_UNKNOWN
1012 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
1013 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1014 self._ValueList[0] = self._SubsectionName
1015
1016 ## Directive statement parser
1017 def _DirectiveParser(self):
1018 self._ValueList = ['', '', '']
1019 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
1020 self._ValueList[0:len(TokenList)] = TokenList
1021
1022 # Syntax check
1023 DirectiveName = self._ValueList[0].upper()
1024 if DirectiveName not in self.DataType:
1025 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
1026 File=self.MetaFile, Line=self._LineIndex + 1)
1027
1028 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
1029 self._InDirective += 1
1030
1031 if DirectiveName in ['!ENDIF']:
1032 self._InDirective -= 1
1033
1034 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
1035 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
1036 File=self.MetaFile, Line=self._LineIndex + 1,
1037 ExtraData=self._CurrentLine)
1038
1039 ItemType = self.DataType[DirectiveName]
1040 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]
1041 if ItemType == MODEL_META_DATA_INCLUDE:
1042 Scope = self._Scope
1043 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:
1044 Scope = self._Scope
1045 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1046 # Remove all directives between !if and !endif, including themselves
1047 while self._DirectiveStack:
1048 # Remove any !else or !elseif
1049 DirectiveInfo = self._DirectiveStack.pop()
1050 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1051 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1052 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1053 break
1054 else:
1055 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
1056 File=self.MetaFile, Line=self._LineIndex + 1,
1057 ExtraData=self._CurrentLine)
1058 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:
1059 # Break if there's a !else is followed by a !elseif
1060 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
1061 self._DirectiveStack and \
1062 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1063 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
1064 File=self.MetaFile, Line=self._LineIndex + 1,
1065 ExtraData=self._CurrentLine)
1066 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
1067
1068 #
1069 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1070 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1071 #
1072 for Arch, ModuleType, DefaultStore in Scope:
1073 self._LastItem = self._Store(
1074 ItemType,
1075 self._ValueList[0],
1076 self._ValueList[1],
1077 self._ValueList[2],
1078 Arch,
1079 ModuleType,
1080 DefaultStore,
1081 self._Owner[-1],
1082 self._From,
1083 self._LineIndex + 1,
1084 - 1,
1085 self._LineIndex + 1,
1086 - 1,
1087 0
1088 )
1089
1090 ## [defines] section parser
1091 @ParseMacro
1092 def _DefineParser(self):
1093 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1094 self._ValueList[1:len(TokenList)] = TokenList
1095
1096 # Syntax check
1097 if not self._ValueList[1]:
1098 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
1099 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1100 if not self._ValueList[2]:
1101 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
1102 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1103 if (not self._ValueList[1] in self.DefineKeywords and
1104 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):
1105 EdkLogger.error('Parser', FORMAT_INVALID,
1106 "Unknown keyword found: %s. "
1107 "If this is a macro you must "
1108 "add it as a DEFINE in the DSC" % self._ValueList[1],
1109 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1110 if not self._InSubsection:
1111 self._Defines[self._ValueList[1]] = self._ValueList[2]
1112 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
1113
1114 @ParseMacro
1115 def _SkuIdParser(self):
1116 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1117 if len(TokenList) not in (2, 3):
1118 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",
1119 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1120 self._ValueList[0:len(TokenList)] = TokenList
1121 @ParseMacro
1122 def _DefaultStoresParser(self):
1123 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1124 if len(TokenList) != 2:
1125 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",
1126 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1127 self._ValueList[0:len(TokenList)] = TokenList
1128
1129 ## Parse Edk style of library modules
1130 @ParseMacro
1131 def _LibraryInstanceParser(self):
1132 self._ValueList[0] = self._CurrentLine
1133
1134 ## PCD sections parser
1135 #
1136 # [PcdsFixedAtBuild]
1137 # [PcdsPatchableInModule]
1138 # [PcdsFeatureFlag]
1139 # [PcdsDynamicEx
1140 # [PcdsDynamicExDefault]
1141 # [PcdsDynamicExVpd]
1142 # [PcdsDynamicExHii]
1143 # [PcdsDynamic]
1144 # [PcdsDynamicDefault]
1145 # [PcdsDynamicVpd]
1146 # [PcdsDynamicHii]
1147 #
1148 @ParseMacro
1149 def _PcdParser(self):
1150 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1151 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1152 PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)
1153 if len(PcdNameTockens) == 2:
1154 self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]
1155 elif len(PcdNameTockens) == 3:
1156 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]
1157 elif len(PcdNameTockens) > 3:
1158 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])
1159 if len(TokenList) == 2:
1160 self._ValueList[2] = TokenList[1]
1161 if self._ValueList[0] == '' or self._ValueList[1] == '':
1162 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1163 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1164 File=self.MetaFile, Line=self._LineIndex + 1)
1165 if self._ValueList[2] == '':
1166 #
1167 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default
1168 #
1169 if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
1170 return
1171 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
1172 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1173 File=self.MetaFile, Line=self._LineIndex + 1)
1174
1175 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1176 ValueList = GetSplitValueList(self._ValueList[2])
1177 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \
1178 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
1179 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
1180 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1181
1182 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string
1183 if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:
1184 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1185 if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:
1186 EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",
1187 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1188
1189 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1190 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1191 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
1192 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
1193 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
1194 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
1195
1196
1197 ## [components] section parser
1198 @ParseMacro
1199 def _ComponentParser(self):
1200 if self._CurrentLine[-1] == '{':
1201 self._ValueList[0] = self._CurrentLine[0:-1].strip()
1202 self._InSubsection = True
1203 self._SubsectionType = MODEL_UNKNOWN
1204 else:
1205 self._ValueList[0] = self._CurrentLine
1206
1207 ## [LibraryClasses] section
1208 @ParseMacro
1209 def _LibraryClassParser(self):
1210 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1211 if len(TokenList) < 2:
1212 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
1213 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1214 File=self.MetaFile, Line=self._LineIndex + 1)
1215 if TokenList[0] == '':
1216 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
1217 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1218 File=self.MetaFile, Line=self._LineIndex + 1)
1219 if TokenList[1] == '':
1220 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
1221 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1222 File=self.MetaFile, Line=self._LineIndex + 1)
1223
1224 self._ValueList[0:len(TokenList)] = TokenList
1225
1226 def _CompponentSourceOverridePathParser(self):
1227 self._ValueList[0] = self._CurrentLine
1228
1229 ## [BuildOptions] section parser
1230 @ParseMacro
1231 def _BuildOptionParser(self):
1232 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
1233 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1234 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
1235 if len(TokenList2) == 2:
1236 self._ValueList[0] = TokenList2[0] # toolchain family
1237 self._ValueList[1] = TokenList2[1] # keys
1238 else:
1239 self._ValueList[1] = TokenList[0]
1240 if len(TokenList) == 2: # value
1241 self._ValueList[2] = TokenList[1]
1242
1243 if self._ValueList[1].count('_') != 4:
1244 EdkLogger.error(
1245 'Parser',
1246 FORMAT_INVALID,
1247 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
1248 ExtraData=self._CurrentLine,
1249 File=self.MetaFile,
1250 Line=self._LineIndex + 1
1251 )
1252
1253 ## Override parent's method since we'll do all macro replacements in parser
1254 @property
1255 def _Macros(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 if self._ItemType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
1615 if ValList[1] != TAB_VOID and ValList[2]:
1616 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect. Only VOID* type PCD need the maxsize info.", File=self._FileWithError,
1617 Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1618 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,
1619 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1620 PcdValue = ValList[Index]
1621 if PcdValue and "." not in self._ValueList[0]:
1622 try:
1623 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
1624 except WrnExpression as Value:
1625 ValList[Index] = Value.result
1626 except:
1627 pass
1628
1629 if ValList[Index] == 'True':
1630 ValList[Index] = '1'
1631 if ValList[Index] == 'False':
1632 ValList[Index] = '0'
1633
1634 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):
1635 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1636 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1637 try:
1638 self._ValueList[2] = '|'.join(ValList)
1639 except Exception:
1640 print(ValList)
1641
1642 def __ProcessComponent(self):
1643 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1644
1645 def __ProcessSourceOverridePath(self):
1646 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1647
1648 def __ProcessBuildOption(self):
1649 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
1650 for Value in self._ValueList]
1651
1652 _SectionParser = {
1653 MODEL_META_DATA_HEADER : _DefineParser,
1654 MODEL_EFI_SKU_ID : _SkuIdParser,
1655 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,
1656 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
1657 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
1658 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1659 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1660 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1661 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
1662 MODEL_PCD_DYNAMIC_HII : _PcdParser,
1663 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
1664 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
1665 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
1666 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
1667 MODEL_META_DATA_COMPONENT : _ComponentParser,
1668 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,
1669 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1670 MODEL_UNKNOWN : MetaFileParser._Skip,
1671 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
1672 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1673 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1674 }
1675
1676 ## DEC file parser class
1677 #
1678 # @param FilePath The path of platform description file
1679 # @param FileType The raw data of DSC file
1680 # @param Table Database used to retrieve module/package information
1681 # @param Macros Macros used for replacement in file
1682 #
1683 class DecParser(MetaFileParser):
1684 # DEC file supported data types (one type per section)
1685 DataType = {
1686 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1687 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1688 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1689 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1690 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1691 TAB_PPIS.upper() : MODEL_EFI_PPI,
1692 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1693 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1694 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1695 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1696 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1697 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1698 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
1699 }
1700
1701 ## Constructor of DecParser
1702 #
1703 # Initialize object of DecParser
1704 #
1705 # @param FilePath The path of platform description file
1706 # @param FileType The raw data of DSC file
1707 # @param Arch Default Arch value for filtering sections
1708 # @param Table Database used to retrieve module/package information
1709 #
1710 def __init__(self, FilePath, FileType, Arch, Table):
1711 # prevent re-initialization
1712 if hasattr(self, "_Table"):
1713 return
1714 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)
1715 self._Comments = []
1716 self._Version = 0x00010005 # Only EDK2 dec file is supported
1717 self._AllPCDs = [] # Only for check duplicate PCD
1718 self._AllPcdDict = {}
1719
1720 self._CurrentStructurePcdName = ""
1721 self._include_flag = False
1722 self._package_flag = False
1723
1724 ## Parser starter
1725 def Start(self):
1726 Content = ''
1727 try:
1728 Content = open(str(self.MetaFile), 'r').readlines()
1729 except:
1730 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1731
1732 self._DefinesCount = 0
1733 for Index in range(0, len(Content)):
1734 Line, Comment = CleanString2(Content[Index])
1735 self._CurrentLine = Line
1736 self._LineIndex = Index
1737
1738 # save comment for later use
1739 if Comment:
1740 self._Comments.append((Comment, self._LineIndex + 1))
1741 # skip empty line
1742 if Line == '':
1743 continue
1744
1745 # section header
1746 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
1747 self._SectionHeaderParser()
1748 if self._SectionName == TAB_DEC_DEFINES.upper():
1749 self._DefinesCount += 1
1750 self._Comments = []
1751 continue
1752 if self._SectionType == MODEL_UNKNOWN:
1753 EdkLogger.error("Parser", FORMAT_INVALID,
1754 ""
1755 "Not able to determine \"%s\" in which section."%self._CurrentLine,
1756 self.MetaFile, self._LineIndex + 1)
1757 elif len(self._SectionType) == 0:
1758 self._Comments = []
1759 continue
1760
1761 # section content
1762 self._ValueList = ['', '', '']
1763 self._SectionParser[self._SectionType[0]](self)
1764 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
1765 self._ItemType = -1
1766 self._Comments = []
1767 continue
1768
1769 #
1770 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1771 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1772 #
1773 for Arch, ModuleType, Type in self._Scope:
1774 self._LastItem = self._Store(
1775 Type,
1776 self._ValueList[0],
1777 self._ValueList[1],
1778 self._ValueList[2],
1779 Arch,
1780 ModuleType,
1781 self._Owner[-1],
1782 self._LineIndex + 1,
1783 - 1,
1784 self._LineIndex + 1,
1785 - 1,
1786 0
1787 )
1788 for Comment, LineNo in self._Comments:
1789 self._Store(
1790 MODEL_META_DATA_COMMENT,
1791 Comment,
1792 self._ValueList[0],
1793 self._ValueList[1],
1794 Arch,
1795 ModuleType,
1796 self._LastItem,
1797 LineNo,
1798 - 1,
1799 LineNo,
1800 - 1,
1801 0
1802 )
1803 self._Comments = []
1804 if self._DefinesCount > 1:
1805 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )
1806 if self._DefinesCount == 0:
1807 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)
1808 self._Done()
1809
1810
1811 ## Section header parser
1812 #
1813 # The section header is always in following format:
1814 #
1815 # [section_name.arch<.platform|module_type>]
1816 #
1817 def _SectionHeaderParser(self):
1818 self._Scope = []
1819 self._SectionName = ''
1820 self._SectionType = []
1821 ArchList = set()
1822 PrivateList = set()
1823 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)
1824 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
1825 if Item == '':
1826 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
1827 "section name can NOT be empty or incorrectly use separator comma",
1828 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1829 ItemList = Item.split(TAB_SPLIT)
1830
1831 # different types of PCD are permissible in one section
1832 self._SectionName = ItemList[0].upper()
1833 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):
1834 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",
1835 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1836 if self._SectionName in self.DataType:
1837 if self.DataType[self._SectionName] not in self._SectionType:
1838 self._SectionType.append(self.DataType[self._SectionName])
1839 else:
1840 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
1841 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1842
1843 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1844 EdkLogger.error(
1845 'Parser',
1846 FORMAT_INVALID,
1847 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1848 File=self.MetaFile,
1849 Line=self._LineIndex + 1,
1850 ExtraData=self._CurrentLine
1851 )
1852 # S1 is always Arch
1853 if len(ItemList) > 1:
1854 S1 = ItemList[1].upper()
1855 else:
1856 S1 = TAB_ARCH_COMMON
1857 ArchList.add(S1)
1858 # S2 may be Platform or ModuleType
1859 if len(ItemList) > 2:
1860 S2 = ItemList[2].upper()
1861 # only Includes, GUIDs, PPIs, Protocols section have Private tag
1862 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:
1863 if S2 != 'PRIVATE':
1864 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',
1865 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1866 else:
1867 S2 = TAB_COMMON
1868 PrivateList.add(S2)
1869 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1870 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1871
1872 # 'COMMON' must not be used with specific ARCHs at the same section
1873 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:
1874 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1875 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1876
1877 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
1878 if TAB_COMMON in PrivateList and len(PrivateList) > 1:
1879 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
1880 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1881
1882 ## [guids], [ppis] and [protocols] section parser
1883 @ParseMacro
1884 def _GuidParser(self):
1885 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1886 if len(TokenList) < 2:
1887 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1888 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1889 File=self.MetaFile, Line=self._LineIndex + 1)
1890 if TokenList[0] == '':
1891 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1892 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1893 File=self.MetaFile, Line=self._LineIndex + 1)
1894 if TokenList[1] == '':
1895 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1896 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1897 File=self.MetaFile, Line=self._LineIndex + 1)
1898 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1899 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1900 ExtraData=self._CurrentLine + \
1901 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1902 File=self.MetaFile, Line=self._LineIndex + 1)
1903 self._ValueList[0] = TokenList[0]
1904 self._ValueList[1] = TokenList[1]
1905 if self._ValueList[0] not in self._GuidDict:
1906 self._GuidDict[self._ValueList[0]] = self._ValueList[1]
1907
1908 ## PCD sections parser
1909 #
1910 # [PcdsFixedAtBuild]
1911 # [PcdsPatchableInModule]
1912 # [PcdsFeatureFlag]
1913 # [PcdsDynamicEx
1914 # [PcdsDynamic]
1915 #
1916 @ParseMacro
1917 def _PcdParser(self):
1918 if self._CurrentStructurePcdName:
1919 self._ValueList[0] = self._CurrentStructurePcdName
1920
1921 if "|" not in self._CurrentLine:
1922 if "<HeaderFiles>" == self._CurrentLine:
1923 self._include_flag = True
1924 self._package_flag = False
1925 self._ValueList = None
1926 return
1927 if "<Packages>" == self._CurrentLine:
1928 self._package_flag = True
1929 self._ValueList = None
1930 self._include_flag = False
1931 return
1932
1933 if self._include_flag:
1934 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()
1935 self._ValueList[2] = self._CurrentLine
1936 if self._package_flag and "}" != self._CurrentLine:
1937 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()
1938 self._ValueList[2] = self._CurrentLine
1939 if self._CurrentLine == "}":
1940 self._package_flag = False
1941 self._include_flag = False
1942 self._ValueList = None
1943 return
1944 else:
1945 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)
1946 PcdNames = PcdTockens[0].split(TAB_SPLIT)
1947 if len(PcdNames) == 2:
1948 self._CurrentStructurePcdName = ""
1949 else:
1950 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):
1951 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),
1952 File=self.MetaFile, Line=self._LineIndex + 1)
1953 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])
1954 self._ValueList[2] = PcdTockens[1]
1955 if not self._CurrentStructurePcdName:
1956 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1957 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1958 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
1959 # check PCD information
1960 if self._ValueList[0] == '' or self._ValueList[1] == '':
1961 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1962 ExtraData=self._CurrentLine + \
1963 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1964 File=self.MetaFile, Line=self._LineIndex + 1)
1965 # check format of token space GUID CName
1966 if not ValueRe.match(self._ValueList[0]):
1967 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_]*'",
1968 ExtraData=self._CurrentLine + \
1969 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1970 File=self.MetaFile, Line=self._LineIndex + 1)
1971 # check format of PCD CName
1972 if not ValueRe.match(self._ValueList[1]):
1973 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1974 ExtraData=self._CurrentLine + \
1975 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1976 File=self.MetaFile, Line=self._LineIndex + 1)
1977 # check PCD datum information
1978 if len(TokenList) < 2 or TokenList[1] == '':
1979 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
1980 ExtraData=self._CurrentLine + \
1981 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1982 File=self.MetaFile, Line=self._LineIndex + 1)
1983
1984
1985 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1986 PtrValue = ValueRe.findall(TokenList[1])
1987
1988 # Has VOID* type string, may contain "|" character in the string.
1989 if len(PtrValue) != 0:
1990 ptrValueList = re.sub(ValueRe, '', TokenList[1])
1991 ValueList = AnalyzePcdExpression(ptrValueList)
1992 ValueList[0] = PtrValue[0]
1993 else:
1994 ValueList = AnalyzePcdExpression(TokenList[1])
1995
1996
1997 # check if there's enough datum information given
1998 if len(ValueList) != 3:
1999 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
2000 ExtraData=self._CurrentLine + \
2001 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2002 File=self.MetaFile, Line=self._LineIndex + 1)
2003 # check default value
2004 if ValueList[0] == '':
2005 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
2006 ExtraData=self._CurrentLine + \
2007 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2008 File=self.MetaFile, Line=self._LineIndex + 1)
2009 # check datum type
2010 if ValueList[1] == '':
2011 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
2012 ExtraData=self._CurrentLine + \
2013 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2014 File=self.MetaFile, Line=self._LineIndex + 1)
2015 # check token of the PCD
2016 if ValueList[2] == '':
2017 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
2018 ExtraData=self._CurrentLine + \
2019 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2020 File=self.MetaFile, Line=self._LineIndex + 1)
2021
2022 PcdValue = ValueList[0]
2023 if PcdValue:
2024 try:
2025 self._GuidDict.update(self._AllPcdDict)
2026 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
2027 except BadExpression as Value:
2028 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
2029 # check format of default value against the datum type
2030 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
2031 if not IsValid:
2032 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
2033 File=self.MetaFile, Line=self._LineIndex + 1)
2034
2035 if Cause == "StructurePcd":
2036 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])
2037 self._ValueList[0] = self._CurrentStructurePcdName
2038 self._ValueList[1] = ValueList[1].strip()
2039
2040 if ValueList[0] in ['True', 'true', 'TRUE']:
2041 ValueList[0] = '1'
2042 elif ValueList[0] in ['False', 'false', 'FALSE']:
2043 ValueList[0] = '0'
2044
2045 # check for duplicate PCD definition
2046 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
2047 EdkLogger.error('Parser', FORMAT_INVALID,
2048 "The same PCD name and GUID have been already defined",
2049 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
2050 else:
2051 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
2052 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]
2053
2054 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
2055
2056 _SectionParser = {
2057 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
2058 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
2059 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
2060 MODEL_EFI_GUID : _GuidParser,
2061 MODEL_EFI_PPI : _GuidParser,
2062 MODEL_EFI_PROTOCOL : _GuidParser,
2063 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
2064 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
2065 MODEL_PCD_FEATURE_FLAG : _PcdParser,
2066 MODEL_PCD_DYNAMIC : _PcdParser,
2067 MODEL_PCD_DYNAMIC_EX : _PcdParser,
2068 MODEL_UNKNOWN : MetaFileParser._Skip,
2069 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
2070 }
2071
2072 ##
2073 #
2074 # This acts like the main() function for the script, unless it is 'import'ed into another
2075 # script.
2076 #
2077 if __name__ == '__main__':
2078 pass
2079