]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools: AutoGen and GenFds share the parser data.
[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 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.Cur, self.MetaFile, MODEL_FILE_DSC, True)
1376 self._Table.Create()
1377 self._DirectiveStack = []
1378 self._DirectiveEvalStack = []
1379 self._FileWithError = self.MetaFile
1380 self._FileLocalMacros = {}
1381 self._SectionsMacroDict.clear()
1382 GlobalData.gPlatformDefines = {}
1383
1384 # Get all macro and PCD which has straitforward value
1385 self.__RetrievePcdValue()
1386 self._Content = self._RawTable.GetAll()
1387 self._ContentIndex = 0
1388 self._InSubsection = False
1389 while self._ContentIndex < len(self._Content) :
1390 Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \
1391 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
1392
1393 if self._From < 0:
1394 self._FileWithError = self.MetaFile
1395
1396 self._ContentIndex += 1
1397
1398 self._Scope = [[S1, S2, S3]]
1399 #
1400 # For !include directive, handle it specially,
1401 # merge arch and module type in case of duplicate items
1402 #
1403 while self._ItemType == MODEL_META_DATA_INCLUDE:
1404 if self._ContentIndex >= len(self._Content):
1405 break
1406 Record = self._Content[self._ContentIndex]
1407 if LineStart == Record[10] and LineEnd == Record[12]:
1408 if [Record[5], Record[6], Record[7]] not in self._Scope:
1409 self._Scope.append([Record[5], Record[6], Record[7]])
1410 self._ContentIndex += 1
1411 else:
1412 break
1413
1414 self._LineIndex = LineStart - 1
1415 self._ValueList = [V1, V2, V3]
1416
1417 if Owner > 0 and Owner in self._IdMapping:
1418 self._InSubsection = True
1419 else:
1420 self._InSubsection = False
1421 try:
1422 Processer[self._ItemType]()
1423 except EvaluationException as Excpt:
1424 #
1425 # Only catch expression evaluation error here. We need to report
1426 # the precise number of line on which the error occurred
1427 #
1428 if hasattr(Excpt, 'Pcd'):
1429 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
1430 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
1431 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
1432 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1433 " of the DSC file, and it is currently defined in this section:"
1434 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
1435 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1436 Line=self._LineIndex + 1)
1437 else:
1438 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
1439 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1440 Line=self._LineIndex + 1)
1441 else:
1442 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1443 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1444 Line=self._LineIndex + 1)
1445 except MacroException as Excpt:
1446 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
1447 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1448 Line=self._LineIndex + 1)
1449
1450 if self._ValueList is None:
1451 continue
1452
1453 NewOwner = self._IdMapping.get(Owner, -1)
1454 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
1455 self._LastItem = self._Store(
1456 self._ItemType,
1457 self._ValueList[0],
1458 self._ValueList[1],
1459 self._ValueList[2],
1460 S1,
1461 S2,
1462 S3,
1463 NewOwner,
1464 self._From,
1465 self._LineIndex + 1,
1466 - 1,
1467 self._LineIndex + 1,
1468 - 1,
1469 self._Enabled
1470 )
1471 self._IdMapping[Id] = self._LastItem
1472
1473 GlobalData.gPlatformDefines.update(self._FileLocalMacros)
1474 self._PostProcessed = True
1475 self._Content = None
1476 def _ProcessError(self):
1477 if not self._Enabled:
1478 return
1479 EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)
1480
1481 def __ProcessSectionHeader(self):
1482 self._SectionName = self._ValueList[0]
1483 if self._SectionName in self.DataType:
1484 self._SectionType = self.DataType[self._SectionName]
1485 else:
1486 self._SectionType = MODEL_UNKNOWN
1487
1488 def __ProcessSubsectionHeader(self):
1489 self._SubsectionName = self._ValueList[0]
1490 if self._SubsectionName in self.DataType:
1491 self._SubsectionType = self.DataType[self._SubsectionName]
1492 else:
1493 self._SubsectionType = MODEL_UNKNOWN
1494
1495 def __RetrievePcdValue(self):
1496 Content = open(str(self.MetaFile), 'r').readlines()
1497 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
1498 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
1499 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
1500 MODEL_PCD_DYNAMIC_EX_VPD):
1501 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
1502 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:
1503 Name = TokenSpaceGuid + '.' + PcdName
1504 if Name not in GlobalData.gPlatformOtherPcds:
1505 PcdLine = Line
1506 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
1507 Line -= 1
1508 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
1509
1510 def __ProcessDefine(self):
1511 if not self._Enabled:
1512 return
1513
1514 Type, Name, Value = self._ValueList
1515 Value = ReplaceMacro(Value, self._Macros, False)
1516 #
1517 # If it is <Defines>, return
1518 #
1519 if self._InSubsection:
1520 self._ValueList = [Type, Name, Value]
1521 return
1522
1523 if self._ItemType == MODEL_META_DATA_DEFINE:
1524 if self._SectionType == MODEL_META_DATA_HEADER:
1525 self._FileLocalMacros[Name] = Value
1526 else:
1527 self._ConstructSectionMacroDict(Name, Value)
1528 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
1529 GlobalData.gEdkGlobal[Name] = Value
1530
1531 #
1532 # Keyword in [Defines] section can be used as Macros
1533 #
1534 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
1535 self._FileLocalMacros[Name] = Value
1536
1537 self._ValueList = [Type, Name, Value]
1538
1539 def __ProcessDirective(self):
1540 Result = None
1541 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1542 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
1543 Macros = self._Macros
1544 Macros.update(GlobalData.gGlobalDefines)
1545 try:
1546 Result = ValueExpression(self._ValueList[1], Macros)()
1547 except SymbolNotFound as Exc:
1548 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1549 Result = False
1550 except WrnExpression as Excpt:
1551 #
1552 # Catch expression evaluation warning here. We need to report
1553 # the precise number of line and return the evaluation result
1554 #
1555 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
1556 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1557 Line=self._LineIndex + 1)
1558 Result = Excpt.result
1559
1560 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1561 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1562 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1563 self._DirectiveStack.append(self._ItemType)
1564 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
1565 Result = bool(Result)
1566 else:
1567 Macro = self._ValueList[1]
1568 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
1569 Result = Macro in self._Macros
1570 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
1571 Result = not Result
1572 self._DirectiveEvalStack.append(Result)
1573 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
1574 self._DirectiveStack.append(self._ItemType)
1575 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1576 self._DirectiveEvalStack.append(bool(Result))
1577 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1578 self._DirectiveStack.append(self._ItemType)
1579 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1580 self._DirectiveEvalStack.append(True)
1581 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1582 # Back to the nearest !if/!ifdef/!ifndef
1583 while self._DirectiveStack:
1584 self._DirectiveEvalStack.pop()
1585 Directive = self._DirectiveStack.pop()
1586 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1587 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1588 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1589 break
1590 elif self._ItemType == MODEL_META_DATA_INCLUDE:
1591 # The included file must be relative to workspace or same directory as DSC file
1592 __IncludeMacros = {}
1593 #
1594 # Allow using system environment variables in path after !include
1595 #
1596 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
1597 if "ECP_SOURCE" in GlobalData.gGlobalDefines:
1598 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']
1599 #
1600 # During GenFds phase call DSC parser, will go into this branch.
1601 #
1602 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines:
1603 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']
1604
1605 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']
1606 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']
1607 #
1608 # Allow using MACROs comes from [Defines] section to keep compatible.
1609 #
1610 __IncludeMacros.update(self._Macros)
1611
1612 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
1613 #
1614 # First search the include file under the same directory as DSC file
1615 #
1616 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
1617 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
1618 if ErrorCode != 0:
1619 #
1620 # Also search file under the WORKSPACE directory
1621 #
1622 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
1623 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
1624 if ErrorCode != 0:
1625 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
1626 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
1627
1628 self._FileWithError = IncludedFile1
1629
1630 FromItem = self._Content[self._ContentIndex - 1][0]
1631 if self._InSubsection:
1632 Owner = self._Content[self._ContentIndex - 1][8]
1633 else:
1634 Owner = self._Content[self._ContentIndex - 1][0]
1635 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)
1636 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,
1637 Owner=Owner, From=FromItem)
1638
1639 self.IncludedFiles.add (IncludedFile1)
1640
1641 # set the parser status with current status
1642 Parser._SectionName = self._SectionName
1643 Parser._SubsectionType = self._SubsectionType
1644 Parser._InSubsection = self._InSubsection
1645 Parser._SectionType = self._SectionType
1646 Parser._Scope = self._Scope
1647 Parser._Enabled = self._Enabled
1648 # Parse the included file
1649 Parser.Start()
1650
1651
1652 # Insert all records in the table for the included file into dsc file table
1653 Records = IncludedFileTable.GetAll()
1654 if Records:
1655 self._Content[self._ContentIndex:self._ContentIndex] = Records
1656 self._Content.pop(self._ContentIndex - 1)
1657 self._ValueList = None
1658 self._ContentIndex -= 1
1659
1660 def __ProcessSkuId(self):
1661 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1662 for Value in self._ValueList]
1663 def __ProcessDefaultStores(self):
1664 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1665 for Value in self._ValueList]
1666
1667 def __ProcessLibraryInstance(self):
1668 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
1669
1670 def __ProcessLibraryClass(self):
1671 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
1672
1673 def __ProcessPcd(self):
1674 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
1675 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
1676 return
1677
1678 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
1679 if not Valid:
1680 if self._ItemType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
1681 if ValList[1] != TAB_VOID and StructPattern.match(ValList[1]) is None and ValList[2]:
1682 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect. The datum type info should be VOID* or a valid struct name.", File=self._FileWithError,
1683 Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1684 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,
1685 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1686 PcdValue = ValList[Index]
1687 if PcdValue and "." not in self._ValueList[0]:
1688 try:
1689 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
1690 except WrnExpression as Value:
1691 ValList[Index] = Value.result
1692 except:
1693 pass
1694
1695 if ValList[Index] == 'True':
1696 ValList[Index] = '1'
1697 if ValList[Index] == 'False':
1698 ValList[Index] = '0'
1699
1700 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):
1701 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1702 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1703 try:
1704 self._ValueList[2] = '|'.join(ValList)
1705 except Exception:
1706 print(ValList)
1707
1708 def __ProcessComponent(self):
1709 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1710
1711 def __ProcessSourceOverridePath(self):
1712 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1713
1714 def __ProcessBuildOption(self):
1715 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
1716 for Value in self._ValueList]
1717
1718 _SectionParser = {
1719 MODEL_META_DATA_HEADER : _DefineParser,
1720 MODEL_EFI_SKU_ID : _SkuIdParser,
1721 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,
1722 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
1723 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
1724 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1725 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1726 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1727 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
1728 MODEL_PCD_DYNAMIC_HII : _PcdParser,
1729 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
1730 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
1731 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
1732 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
1733 MODEL_META_DATA_COMPONENT : _ComponentParser,
1734 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,
1735 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1736 MODEL_UNKNOWN : MetaFileParser._Skip,
1737 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
1738 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1739 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1740 }
1741
1742 ## DEC file parser class
1743 #
1744 # @param FilePath The path of platform description file
1745 # @param FileType The raw data of DSC file
1746 # @param Table Database used to retrieve module/package information
1747 # @param Macros Macros used for replacement in file
1748 #
1749 class DecParser(MetaFileParser):
1750 # DEC file supported data types (one type per section)
1751 DataType = {
1752 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1753 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1754 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1755 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1756 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1757 TAB_PPIS.upper() : MODEL_EFI_PPI,
1758 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1759 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1760 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1761 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1762 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1763 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1764 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
1765 }
1766
1767 ## Constructor of DecParser
1768 #
1769 # Initialize object of DecParser
1770 #
1771 # @param FilePath The path of platform description file
1772 # @param FileType The raw data of DSC file
1773 # @param Arch Default Arch value for filtering sections
1774 # @param Table Database used to retrieve module/package information
1775 #
1776 def __init__(self, FilePath, FileType, Arch, Table):
1777 # prevent re-initialization
1778 if hasattr(self, "_Table"):
1779 return
1780 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)
1781 self._Comments = []
1782 self._Version = 0x00010005 # Only EDK2 dec file is supported
1783 self._AllPCDs = [] # Only for check duplicate PCD
1784 self._AllPcdDict = {}
1785
1786 self._CurrentStructurePcdName = ""
1787 self._include_flag = False
1788 self._package_flag = False
1789
1790 ## Parser starter
1791 def Start(self):
1792 Content = ''
1793 try:
1794 Content = open(str(self.MetaFile), 'r').readlines()
1795 except:
1796 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1797
1798 self._DefinesCount = 0
1799 for Index in range(0, len(Content)):
1800 Line, Comment = CleanString2(Content[Index])
1801 self._CurrentLine = Line
1802 self._LineIndex = Index
1803
1804 # save comment for later use
1805 if Comment:
1806 self._Comments.append((Comment, self._LineIndex + 1))
1807 # skip empty line
1808 if Line == '':
1809 continue
1810
1811 # section header
1812 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
1813 self._SectionHeaderParser()
1814 if self._SectionName == TAB_DEC_DEFINES.upper():
1815 self._DefinesCount += 1
1816 self._Comments = []
1817 continue
1818 if self._SectionType == MODEL_UNKNOWN:
1819 EdkLogger.error("Parser", FORMAT_INVALID,
1820 ""
1821 "Not able to determine \"%s\" in which section."%self._CurrentLine,
1822 self.MetaFile, self._LineIndex + 1)
1823 elif len(self._SectionType) == 0:
1824 self._Comments = []
1825 continue
1826
1827 # section content
1828 self._ValueList = ['', '', '']
1829 self._SectionParser[self._SectionType[0]](self)
1830 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
1831 self._ItemType = -1
1832 self._Comments = []
1833 continue
1834
1835 #
1836 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1837 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1838 #
1839 for Arch, ModuleType, Type in self._Scope:
1840 self._LastItem = self._Store(
1841 Type,
1842 self._ValueList[0],
1843 self._ValueList[1],
1844 self._ValueList[2],
1845 Arch,
1846 ModuleType,
1847 self._Owner[-1],
1848 self._LineIndex + 1,
1849 - 1,
1850 self._LineIndex + 1,
1851 - 1,
1852 0
1853 )
1854 for Comment, LineNo in self._Comments:
1855 self._Store(
1856 MODEL_META_DATA_COMMENT,
1857 Comment,
1858 self._ValueList[0],
1859 self._ValueList[1],
1860 Arch,
1861 ModuleType,
1862 self._LastItem,
1863 LineNo,
1864 - 1,
1865 LineNo,
1866 - 1,
1867 0
1868 )
1869 self._Comments = []
1870 if self._DefinesCount > 1:
1871 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )
1872 if self._DefinesCount == 0:
1873 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)
1874 self._Done()
1875
1876
1877 ## Section header parser
1878 #
1879 # The section header is always in following format:
1880 #
1881 # [section_name.arch<.platform|module_type>]
1882 #
1883 def _SectionHeaderParser(self):
1884 self._Scope = []
1885 self._SectionName = ''
1886 self._SectionType = []
1887 ArchList = set()
1888 PrivateList = set()
1889 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)
1890 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
1891 if Item == '':
1892 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
1893 "section name can NOT be empty or incorrectly use separator comma",
1894 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1895 ItemList = Item.split(TAB_SPLIT)
1896
1897 # different types of PCD are permissible in one section
1898 self._SectionName = ItemList[0].upper()
1899 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):
1900 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",
1901 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1902 if self._SectionName in self.DataType:
1903 if self.DataType[self._SectionName] not in self._SectionType:
1904 self._SectionType.append(self.DataType[self._SectionName])
1905 else:
1906 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
1907 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1908
1909 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1910 EdkLogger.error(
1911 'Parser',
1912 FORMAT_INVALID,
1913 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1914 File=self.MetaFile,
1915 Line=self._LineIndex + 1,
1916 ExtraData=self._CurrentLine
1917 )
1918 # S1 is always Arch
1919 if len(ItemList) > 1:
1920 S1 = ItemList[1].upper()
1921 else:
1922 S1 = TAB_ARCH_COMMON
1923 ArchList.add(S1)
1924 # S2 may be Platform or ModuleType
1925 if len(ItemList) > 2:
1926 S2 = ItemList[2].upper()
1927 # only Includes, GUIDs, PPIs, Protocols section have Private tag
1928 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:
1929 if S2 != 'PRIVATE':
1930 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',
1931 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1932 else:
1933 S2 = TAB_COMMON
1934 PrivateList.add(S2)
1935 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1936 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1937
1938 # 'COMMON' must not be used with specific ARCHs at the same section
1939 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:
1940 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1941 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1942
1943 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
1944 if TAB_COMMON in PrivateList and len(PrivateList) > 1:
1945 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
1946 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1947
1948 ## [guids], [ppis] and [protocols] section parser
1949 @ParseMacro
1950 def _GuidParser(self):
1951 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1952 if len(TokenList) < 2:
1953 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1954 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1955 File=self.MetaFile, Line=self._LineIndex + 1)
1956 if TokenList[0] == '':
1957 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1958 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1959 File=self.MetaFile, Line=self._LineIndex + 1)
1960 if TokenList[1] == '':
1961 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1962 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1963 File=self.MetaFile, Line=self._LineIndex + 1)
1964 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1965 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1966 ExtraData=self._CurrentLine + \
1967 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1968 File=self.MetaFile, Line=self._LineIndex + 1)
1969 self._ValueList[0] = TokenList[0]
1970 self._ValueList[1] = TokenList[1]
1971 if self._ValueList[0] not in self._GuidDict:
1972 self._GuidDict[self._ValueList[0]] = self._ValueList[1]
1973
1974 def ParsePcdName(self,namelist):
1975 if "[" in namelist[1]:
1976 pcdname = namelist[1][:namelist[1].index("[")]
1977 arrayindex = namelist[1][namelist[1].index("["):]
1978 namelist[1] = pcdname
1979 if len(namelist) == 2:
1980 namelist.append(arrayindex)
1981 else:
1982 namelist[2] = ".".join((arrayindex,namelist[2]))
1983 return namelist
1984
1985 ## PCD sections parser
1986 #
1987 # [PcdsFixedAtBuild]
1988 # [PcdsPatchableInModule]
1989 # [PcdsFeatureFlag]
1990 # [PcdsDynamicEx
1991 # [PcdsDynamic]
1992 #
1993 @ParseMacro
1994 def _PcdParser(self):
1995 if self._CurrentStructurePcdName:
1996 self._ValueList[0] = self._CurrentStructurePcdName
1997
1998 if "|" not in self._CurrentLine:
1999 if "<HeaderFiles>" == self._CurrentLine:
2000 self._include_flag = True
2001 self._package_flag = False
2002 self._ValueList = None
2003 return
2004 if "<Packages>" == self._CurrentLine:
2005 self._package_flag = True
2006 self._ValueList = None
2007 self._include_flag = False
2008 return
2009
2010 if self._include_flag:
2011 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine).hexdigest()
2012 self._ValueList[2] = self._CurrentLine
2013 if self._package_flag and "}" != self._CurrentLine:
2014 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine).hexdigest()
2015 self._ValueList[2] = self._CurrentLine
2016 if self._CurrentLine == "}":
2017 self._package_flag = False
2018 self._include_flag = False
2019 self._ValueList = None
2020 return
2021 else:
2022 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)
2023 PcdNames = self.ParsePcdName(PcdTockens[0].split(TAB_SPLIT))
2024 if len(PcdNames) == 2:
2025 if PcdNames[1].strip().endswith("]"):
2026 PcdName = PcdNames[1][:PcdNames[1].index('[')]
2027 Index = PcdNames[1][PcdNames[1].index('['):]
2028 self._ValueList[0] = TAB_SPLIT.join((PcdNames[0],PcdName))
2029 self._ValueList[1] = Index
2030 self._ValueList[2] = PcdTockens[1]
2031 else:
2032 self._CurrentStructurePcdName = ""
2033 else:
2034 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):
2035 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),
2036 File=self.MetaFile, Line=self._LineIndex + 1)
2037 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])
2038 self._ValueList[2] = PcdTockens[1]
2039 if not self._CurrentStructurePcdName:
2040 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
2041 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
2042 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
2043 # check PCD information
2044 if self._ValueList[0] == '' or self._ValueList[1] == '':
2045 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
2046 ExtraData=self._CurrentLine + \
2047 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2048 File=self.MetaFile, Line=self._LineIndex + 1)
2049 # check format of token space GUID CName
2050 if not ValueRe.match(self._ValueList[0]):
2051 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_]*'",
2052 ExtraData=self._CurrentLine + \
2053 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2054 File=self.MetaFile, Line=self._LineIndex + 1)
2055 # check format of PCD CName
2056 if not ValueRe.match(self._ValueList[1]):
2057 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
2058 ExtraData=self._CurrentLine + \
2059 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2060 File=self.MetaFile, Line=self._LineIndex + 1)
2061 # check PCD datum information
2062 if len(TokenList) < 2 or TokenList[1] == '':
2063 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
2064 ExtraData=self._CurrentLine + \
2065 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2066 File=self.MetaFile, Line=self._LineIndex + 1)
2067
2068
2069 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
2070 PtrValue = ValueRe.findall(TokenList[1])
2071
2072 # Has VOID* type string, may contain "|" character in the string.
2073 if len(PtrValue) != 0:
2074 ptrValueList = re.sub(ValueRe, '', TokenList[1])
2075 ValueList = AnalyzePcdExpression(ptrValueList)
2076 ValueList[0] = PtrValue[0]
2077 else:
2078 ValueList = AnalyzePcdExpression(TokenList[1])
2079
2080
2081 # check if there's enough datum information given
2082 if len(ValueList) != 3:
2083 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
2084 ExtraData=self._CurrentLine + \
2085 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2086 File=self.MetaFile, Line=self._LineIndex + 1)
2087 # check default value
2088 if ValueList[0] == '':
2089 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
2090 ExtraData=self._CurrentLine + \
2091 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2092 File=self.MetaFile, Line=self._LineIndex + 1)
2093 # check datum type
2094 if ValueList[1] == '':
2095 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
2096 ExtraData=self._CurrentLine + \
2097 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2098 File=self.MetaFile, Line=self._LineIndex + 1)
2099 # check token of the PCD
2100 if ValueList[2] == '':
2101 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
2102 ExtraData=self._CurrentLine + \
2103 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2104 File=self.MetaFile, Line=self._LineIndex + 1)
2105
2106 PcdValue = ValueList[0]
2107 if PcdValue:
2108 try:
2109 self._GuidDict.update(self._AllPcdDict)
2110 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
2111 except BadExpression as Value:
2112 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
2113 # check format of default value against the datum type
2114 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
2115 if not IsValid:
2116 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
2117 File=self.MetaFile, Line=self._LineIndex + 1)
2118
2119 if Cause == "StructurePcd":
2120 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])
2121 self._ValueList[0] = self._CurrentStructurePcdName
2122 self._ValueList[1] = ValueList[1].strip()
2123
2124 if ValueList[0] in ['True', 'true', 'TRUE']:
2125 ValueList[0] = '1'
2126 elif ValueList[0] in ['False', 'false', 'FALSE']:
2127 ValueList[0] = '0'
2128
2129 # check for duplicate PCD definition
2130 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
2131 EdkLogger.error('Parser', FORMAT_INVALID,
2132 "The same PCD name and GUID have been already defined",
2133 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
2134 else:
2135 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
2136 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]
2137
2138 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
2139
2140 _SectionParser = {
2141 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
2142 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
2143 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
2144 MODEL_EFI_GUID : _GuidParser,
2145 MODEL_EFI_PPI : _GuidParser,
2146 MODEL_EFI_PROTOCOL : _GuidParser,
2147 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
2148 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
2149 MODEL_PCD_FEATURE_FLAG : _PcdParser,
2150 MODEL_PCD_DYNAMIC : _PcdParser,
2151 MODEL_PCD_DYNAMIC_EX : _PcdParser,
2152 MODEL_UNKNOWN : MetaFileParser._Skip,
2153 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
2154 }
2155
2156 ##
2157 #
2158 # This acts like the main() function for the script, unless it is 'import'ed into another
2159 # script.
2160 #
2161 if __name__ == '__main__':
2162 pass
2163