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