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